Lets us read the file.
library(readr)
lyrics <- read_csv("songdata.csv")
head(lyrics)
Lets us examine the dimension of the lyrics dataframe.
dim(lyrics)
[1] 57650 4
library(dplyr)
Attaching package: 'dplyr'
The following objects are masked from 'package:stats':
filter, lag
The following objects are masked from 'package:base':
intersect, setdiff, setequal, union
glimpse(lyrics)
Observations: 57,650
Variables: 4
$ artist <chr> "ABBA", "ABBA", "ABBA", "ABBA", "ABBA", "ABBA", "ABBA", "ABBA", "ABBA", "ABBA", "ABBA", "ABBA", "A...
$ song <chr> "Ahe's My Kind Of Girl", "Andante, Andante", "As Good As New", "Bang", "Bang-A-Boomerang", "Burnin...
$ link <chr> "/a/abba/ahes+my+kind+of+girl_20598417.html", "/a/abba/andante+andante_20002708.html", "/a/abba/as...
$ text <chr> "Look at her face, it's a wonderful face \nAnd it means something special to me \nLook at the wa...
Analysis of 55000+ lyrics data - Number of artists - Which artist has highest and lowest number of songs - Distribution of songs of all artists in the dataset - Distribution of lyrics length - Which song lyrics has maximum number of words - Which song lyrics has minimum number of words - Distribution of words count in title - Which songs title has maximum number of words - Which songs title has minimum number of words - WordClouds of titles with minimum and maximum lengths - Is there a relation between title length and song length?
- Sentiments of the songs (NRC, Bing)
- Which words are most occuring in the lyrics of the songs
- Is there a correlation between the words in the songs of same artists?
- Wordcloud of most popular words in the songs
- Top words used by an artist in his/her songs
- Are there some common Rythmic words that repeats again and again?
Let’s start with finding out how many artists are listed in the data. Also, how many songs each artist has.
artist<- as.data.frame(table(as.data.frame(lyrics$artist)))
colnames(artist) <- c("artist", "Num_of_songs")
head(artist)
Let’s see the which artist has most and least number of songs in the dataset.
most_songs <- arrange(artist, desc(Num_of_songs))
most_songs
Loading required package: lattice
Loading required package: plyr
--------------------------------------------------------------------------------------------------------------------
You have loaded plyr after dplyr - this is likely to cause problems.
If you need functions from both plyr and dplyr, please load plyr first, then dplyr:
library(plyr); library(dplyr)
--------------------------------------------------------------------------------------------------------------------
Attaching package: 'plyr'
The following objects are masked from 'package:dplyr':
arrange, count, desc, failwith, id, mutate, rename, summarise, summarize

least_songs <- tail(most_songs, 15)
p2 <- ggplot(data = least_songs, aes(artist, Num_of_songs, fill = Num_of_songs)) +
geom_bar(stat = "identity") +
geom_text(aes(label=Num_of_songs), vjust=1.6, color="white", size=3) +
ggtitle("Artists with least number of songs") +
tilt_theme
p2

Let’s check the distribution of songs for all artists.
p3 <- ggplot(artist, aes(x=Num_of_songs)) +
geom_histogram(aes(y=..density..), colour="black", fill="white")+
geom_density(alpha=.2, fill="red")
p3

Let’s analyze the number of words in each song and its distribution.
library(stringr)
count_words <- function(vec){
return (length(unlist((str_extract_all(tolower(vec), '\\w+')))))
}
lyrics$word_count <- sapply(lyrics$text, count_words)
head(lyrics$word_count)
[1] 161 272 322 257 255 115
p4 <- ggplot(lyrics, aes(x=word_count)) +
geom_histogram(aes(y=..density..), colour="black", fill="white")+
geom_density(alpha=.2, fill="red")
p4

Let’s analyze the title of the songs, their wordcount and their distribution
lyrics$title_word_count <- sapply(lyrics$song, count_words)
head(lyrics$title_word_count)
[1] 6 2 4 1 3 3
Let’s check out the songs that are longest and shortest.
longest_song <- arrange(lyrics, desc(word_count))
longest_song <- head(longest_song, 10)
shortest_song <- arrange(lyrics, word_count)
shortest_song <- head(shortest_song, 10)
longest_song
shortest_song
p5 <- ggplot(data = longest_song, aes(song, word_count, fill = title_word_count)) +
geom_bar(stat = "identity") +
geom_text(aes(label=title_word_count), vjust=1.6, color="white", size=3) +
ggtitle("Longest Songs") +
tilt_theme
p6 <- ggplot(data = shortest_song, aes(song, word_count, fill = title_word_count)) +
geom_bar(position = "dodge", stat = "identity") +
geom_text(aes(label = title_word_count), vjust = 1.6, color = "white", size = 3) +
ggtitle("Shortest Songs") +
tilt_theme
multiplot(p5, p6, cols=2)

p7 <- ggplot(lyrics, aes(x=title_word_count)) +
geom_histogram(aes(y=..density..), colour="black", fill="white", binwidth = 1, bins = 1)+
geom_density(alpha=.2, fill="red")
p7

WordCloud of popular words from song titles
library(wordcloud)
Loading required package: RColorBrewer
library(SnowballC)
library(RColorBrewer)
library(tm)
Loading required package: NLP
Attaching package: 'NLP'
The following object is masked from 'package:ggplot2':
annotate
texts <- lyrics$song
#texts <- iconv(texts, to = "utf-8")
corpus <- Corpus(VectorSource(texts))
corpus <- tm_map(corpus, PlainTextDocument)
corpus <- tm_map(corpus, removePunctuation)
corpus <- tm_map(corpus, removeWords, stopwords('english'))
corpus <- tm_map(corpus, stemDocument)
corpus <- tm_map(corpus, removeWords, c("and", "this", "there"))
corpus <- Corpus(VectorSource(corpus))
dtm <- TermDocumentMatrix(corpus)
m <- as.matrix(dtm)
v <- sort(rowSums(m),decreasing=TRUE)
d <- data.frame(word = names(v),freq=v)
head(d, 10)
d <- d[-which(d$word %in% c("and","this","that")),]
set.seed(1234)
wordcloud(words = d$word, freq = d$freq, min.freq = 1,
max.words=200, random.order=FALSE, rot.per=0.35,
colors=brewer.pal(8, "Dark2"))

There are many song titles that are of length 1, 2 and 3. But surprisingly, there are titles of length more than 13 too. Let’s check them out.
longest_title <- subset(lyrics, lyrics$title_word_count > 13)
longest_title
shortest_title <- subset(lyrics, lyrics$title_word_count == 1)
shortest_title
There are 8 songs with title length more than 13 and 8342 songs with single word title. Let’s see word cloud of single word titles and longest titles
texts <- longest_title$song
corpus <- Corpus(VectorSource(texts))
corpus <- tm_map(corpus, PlainTextDocument)
corpus <- Corpus(VectorSource(corpus))
dtm <- TermDocumentMatrix(corpus)
m <- as.matrix(dtm)
v <- sort(rowSums(m),decreasing=TRUE)
d <- data.frame(word = names(v),freq=v)
head(d, 10)
set.seed(1234)
wordcloud(words = d$word, freq = d$freq, min.freq = 1,scale=c(2,0.5),
max.words=100, random.order=FALSE, rot.per=0.35,
colors=brewer.pal(8, "Dark2"))

texts <- shortest_title$song
corpus <- Corpus(VectorSource(texts))
corpus <- tm_map(corpus, PlainTextDocument)
corpus <- Corpus(VectorSource(corpus))
dtm <- TermDocumentMatrix(corpus)
m <- as.matrix(dtm)
v <- sort(rowSums(m),decreasing=TRUE)
d <- data.frame(word = names(v),freq=v)
head(d, 10)
set.seed(1234)
wordcloud(words = d$word, freq = d$freq, min.freq = 1,scale=c(2,0.5),
max.words=100, random.order=FALSE, rot.per=0.35,
colors=brewer.pal(8, "Dark2"))

An interesting questin would be is there relation between length of title and songs? Most probably now, but let’s check out.
p8 <- ggplot(lyrics, aes(x=factor(title_word_count), y=word_count, fill = factor(title_word_count))) +
geom_boxplot()
p8

cor(lyrics$title_word_count, lyrics$word_count)
[1] -0.02509779
As expected, there is no correlation between these two quantitites.
Let us fix the contracted words to their full forms first.
# function to expand contractions in an English-language source
fix.contractions <- function(doc) {
# "won't" is a special case as it does not expand to "wo not"
doc <- gsub("won't", "will not", doc)
doc <- gsub("can't", "can not", doc)
doc <- gsub("n't", " not", doc)
doc <- gsub("'ll", " will", doc)
doc <- gsub("'re", " are", doc)
doc <- gsub("'ve", " have", doc)
doc <- gsub("'m", " am", doc)
doc <- gsub("'d", " would", doc)
# 's could be 'is' or could be possessive: it has no expansion
doc <- gsub("'s", "", doc)
return(doc)
}
# fix (expand) contractions
lyrics$text <- sapply(lyrics$text, fix.contractions)
Remove special characters from lyrics
# function to remove special characters
removeSpecialChars <- function(x) gsub("[^a-zA-Z0-9 ]", " ", x)
# remove special characters
lyrics$text <- sapply(lyrics$text, removeSpecialChars)
Convert all lyrics text to lower case
# convert everything to lower case
lyrics$text <- sapply(lyrics$text, tolower)
Let’s check the structure of one lyrics to see the changes.
str(lyrics[13, ]$text, nchar.max = 300)
chr "changing moving in a circle i can see your face in all of my dreams smiling laughing from the shadows when i hear your voice i know what it means i know it does not matter just how hard i try you are all the reason for my life disillusion disillusion all you left "| __truncated__
SENTIMENT ANALYSIS OF LYRICS Let us perform sentiment analysis on the lyrics. There are various types of sentiment lexicons that can be used. Lets us have a look on them.
library(tidytext)
package 'tidytext' was built under R version 3.4.4
library(tidyr)
get_sentiments("afinn")
get_sentiments("bing")
get_sentiments("nrc")
get_sentiments("loughran")
nrc seems to have large number of words and their sentiments compared to other two.
nrc_sentiment <- get_sentiments("nrc")
unique(nrc_sentiment$sentiment)
[1] "trust" "fear" "negative" "sadness" "anger" "surprise" "positive"
[8] "disgust" "joy" "anticipation"
Let us find the sentiments of each lyrics based on each NRC sentiments.
lyrics_words <- select(lyrics, c("artist", "text"))
lyrics_words <- lyrics_words %>% unnest_tokens(word, text)
head(lyrics_words)
dim(lyrics_words)
[1] 13186646 2
Let’s see words that depict “joy”
joy <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "joy"))
Joining, by = "word"
joy <- as.data.frame(sort(table(joy$word)))
columns_sentiment <- c("word", "Freq")
colnames(joy) <- columns_sentiment
tail(joy, 10)
Similarly, let’s see other words that represents other 9 sentiments.
trust <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "trust"))
Joining, by = "word"
trust <- as.data.frame(sort(table(trust$word)))
colnames(trust) <- columns_sentiment
tail(trust, 10)
fear <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "fear"))
Joining, by = "word"
fear <- as.data.frame(sort(table(fear$word)))
colnames(fear) <- columns_sentiment
sadness <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "sadness"))
Joining, by = "word"
sadness <- as.data.frame(sort(table(sadness$word)))
colnames(sadness) <- columns_sentiment
anger <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "anger"))
Joining, by = "word"
anger <- as.data.frame(sort(table(anger$word)))
colnames(anger) <- columns_sentiment
surprise <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "surprise"))
Joining, by = "word"
surprise <- as.data.frame(sort(table(surprise$word)))
colnames(surprise) <- columns_sentiment
disgust <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "disgust"))
Joining, by = "word"
disgust <- as.data.frame(sort(table(disgust$word)))
colnames(disgust) <- columns_sentiment
anticipation <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "anticipation"))
Joining, by = "word"
anticipation <- as.data.frame(sort(table(anticipation$word)))
colnames(anticipation) <- columns_sentiment
Let’s plot the word occurences for each sentiment (except positive and negative)

Let’s plot the wordcloud for each category

Let us check top words that depicts “positive” and “negative” sentiments in NRC Sentiment category.
Joining, by = "word"
Joining, by = "word"

Let us check top words that depicts “positive” and “negative” sentiments in bing Sentiment category.
Joining, by = "word"
Joining, by = "word"
Joining, by = "word"
Joining, by = "word"

It can be seen that positive and negative words are different for all three lexicons.
Let’s plot positive and negative word cloud

Let’s check songs based on NRC sentiment (except positive and negative)
lyrics_words <- select(lyrics, c("artist", "song","text"))
lyrics_words <- lyrics_words %>% unnest_tokens(word, text)
head(lyrics_words)
dim(lyrics_words)
[1] 13186646 3
joy_s <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "joy"))
Joining, by = "word"
joy_s <- as.data.frame(sort(table(joy_s$song)))
columns_sentiment <- c("Song", "Freq")
colnames(joy_s) <- columns_sentiment
tail(joy_s, 10)
trust_s <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "trust"))
Joining, by = "word"
trust_s <- as.data.frame(sort(table(trust_s$song)))
colnames(trust_s) <- columns_sentiment
tail(trust_s, 10)
fear_s <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "fear"))
Joining, by = "word"
fear_s <- as.data.frame(sort(table(fear_s$song)))
colnames(fear_s) <- columns_sentiment
sadness_s <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "sadness"))
Joining, by = "word"
sadness_s <- as.data.frame(sort(table(sadness_s$song)))
colnames(sadness_s) <- columns_sentiment
anger_s <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "anger"))
Joining, by = "word"
anger_s <- as.data.frame(sort(table(anger_s$song)))
colnames(anger_s) <- columns_sentiment
surprise_s <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "surprise"))
Joining, by = "word"
surprise_s <- as.data.frame(sort(table(surprise_s$song)))
colnames(surprise_s) <- columns_sentiment
disgust_s <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "disgust"))
Joining, by = "word"
disgust_s <- as.data.frame(sort(table(disgust_s$song)))
colnames(disgust_s) <- columns_sentiment
anticipation_s <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "anticipation"))
Joining, by = "word"
anticipation_s <- as.data.frame(sort(table(anticipation_s$song)))
colnames(anticipation_s) <- columns_sentiment
Let’s plot the top 10 songs in each category

Let’s do the same for Positive and Negative sentiment in NRC lexicon cateogory.
Joining, by = "word"
Joining, by = "word"

Let us find positive and negative songs based on bing and loughran lexicon cateogories.
Joining, by = "word"
Joining, by = "word"
Joining, by = "word"
Joining, by = "word"

The positive and negative songs in each category are different. This is something known already, since the positive words and negative words in ech categories were also different.
The same analysis can be done for artists. Let’s check out artists who write most songs in each NRC lexicon sentiment cateogry.
joy_a <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "joy"))
Joining, by = "word"
joy_a <- as.data.frame(sort(table(joy_a$artist)))
columns_sentiment <- c("artist", "Freq")
colnames(joy_a) <- columns_sentiment
tail(joy_a, 10)
trust_a <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "trust"))
Joining, by = "word"
trust_a <- as.data.frame(sort(table(trust_a$artist)))
colnames(trust_a) <- columns_sentiment
tail(trust_a, 10)
fear_a <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "fear"))
Joining, by = "word"
fear_a <- as.data.frame(sort(table(fear_a$artist)))
colnames(fear_a) <- columns_sentiment
sadness_a <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "sadness"))
Joining, by = "word"
sadness_a <- as.data.frame(sort(table(sadness_a$artist)))
colnames(sadness_a) <- columns_sentiment
anger_a <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "anger"))
Joining, by = "word"
anger_a <- as.data.frame(sort(table(anger_a$artist)))
colnames(anger_a) <- columns_sentiment
surprise_a <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "surprise"))
Joining, by = "word"
surprise_a <- as.data.frame(sort(table(surprise_a$artist)))
colnames(surprise_a) <- columns_sentiment
disgust_a <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "disgust"))
Joining, by = "word"
disgust_a <- as.data.frame(sort(table(disgust_a$artist)))
colnames(disgust_a) <- columns_sentiment
anticipation_a <- lyrics_words %>%
inner_join(get_sentiments("nrc") %>%
filter(sentiment == "anticipation"))
Joining, by = "word"
anticipation_a <- as.data.frame(sort(table(anticipation_a$artist)))
colnames(anticipation_a) <- columns_sentiment
Let’s plot the top 10 artists in each category

Let’s do the same for Positive and Negative sentiment in NRC lexicon cateogory.
Joining, by = "word"
Joining, by = "word"

Let us find positive and negative songs based on bing and loughran lexicon cateogories.
Joining, by = "word"
Joining, by = "word"
Joining, by = "word"
Joining, by = "word"

Let’s check out bigrams in the songs lyrics
Error in unnest_tokens(lyrics, input = text, output = bigram, token = "ngrams", :
could not find function "unnest_tokens"
bigram_counts <- bigram_united %>%
count(bigram, sort = TRUE)
head(bigram_counts)
bigram_counts %>% arrange(desc(n))%>% head(20)%>%ggplot(aes(x=factor(bigram,levels=bigram),y=n))+geom_bar(stat="identity",fill="#FF3E45")+labs(title="Top 20 bigram words in Songs")+coord_flip()
wordcloud(bigram_counts$bigram,bigram_counts$n,max.words=50,random.order = F,colors=c("#9E0142", "#D53E4F", "#F46D43" ,"#FDAE61", "#FEE08B", "#E6F598" ,"#ABDDA4" ,"#66C2A5" ,"#3288BD", "#5E4FA2"))
title(main="Bigram wordcloud")
LS0tCnRpdGxlOiAiTHlyaWNzIEFuYWx5c2lzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpMZXRzIHVzIHJlYWQgdGhlIGZpbGUuCgpgYGB7cn0KbGlicmFyeShyZWFkcikKbHlyaWNzIDwtIHJlYWRfY3N2KCJzb25nZGF0YS5jc3YiKQpoZWFkKGx5cmljcykKYGBgCgpMZXRzIHVzIGV4YW1pbmUgdGhlIGRpbWVuc2lvbiBvZiB0aGUgbHlyaWNzIGRhdGFmcmFtZS4KCmBgYHtyfQpkaW0obHlyaWNzKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpnbGltcHNlKGx5cmljcykKYGBgCgpBbmFseXNpcyBvZiA1NTAwMCsgbHlyaWNzIGRhdGEKLSBOdW1iZXIgb2YgYXJ0aXN0cwotIFdoaWNoIGFydGlzdCBoYXMgaGlnaGVzdCBhbmQgbG93ZXN0IG51bWJlciBvZiBzb25ncyAKLSBEaXN0cmlidXRpb24gb2Ygc29uZ3Mgb2YgYWxsIGFydGlzdHMgaW4gdGhlIGRhdGFzZXQKLSBEaXN0cmlidXRpb24gb2YgbHlyaWNzIGxlbmd0aAotIFdoaWNoIHNvbmcgbHlyaWNzIGhhcyBtYXhpbXVtIG51bWJlciBvZiB3b3JkcwotIFdoaWNoIHNvbmcgbHlyaWNzIGhhcyBtaW5pbXVtIG51bWJlciBvZiB3b3JkcwotIERpc3RyaWJ1dGlvbiBvZiB3b3JkcyBjb3VudCBpbiB0aXRsZQotIFdoaWNoIHNvbmdzIHRpdGxlIGhhcyBtYXhpbXVtIG51bWJlciBvZiB3b3JkcyAKLSBXaGljaCBzb25ncyB0aXRsZSBoYXMgbWluaW11bSBudW1iZXIgb2Ygd29yZHMKLSBXb3JkQ2xvdWRzIG9mIHRpdGxlcyB3aXRoIG1pbmltdW0gYW5kIG1heGltdW0gbGVuZ3RocwotIElzIHRoZXJlIGEgcmVsYXRpb24gYmV0d2VlbiB0aXRsZSBsZW5ndGggYW5kIHNvbmcgbGVuZ3RoPwoKCi0gU2VudGltZW50cyBvZiB0aGUgc29uZ3MgKE5SQywgQmluZykKLSBXaGljaCB3b3JkcyBhcmUgbW9zdCBvY2N1cmluZyBpbiB0aGUgbHlyaWNzIG9mIHRoZSBzb25ncwotIElzIHRoZXJlIGEgY29ycmVsYXRpb24gYmV0d2VlbiB0aGUgd29yZHMgaW4gdGhlIHNvbmdzIG9mIHNhbWUgYXJ0aXN0cz8KLSBXb3JkY2xvdWQgb2YgbW9zdCBwb3B1bGFyIHdvcmRzIGluIHRoZSBzb25ncwotIFRvcCB3b3JkcyB1c2VkIGJ5IGFuIGFydGlzdCBpbiBoaXMvaGVyIHNvbmdzCi0gQXJlIHRoZXJlIHNvbWUgY29tbW9uIFJ5dGhtaWMgd29yZHMgdGhhdCByZXBlYXRzIGFnYWluIGFuZCBhZ2Fpbj8KCgpMZXQncyBzdGFydCB3aXRoIGZpbmRpbmcgb3V0IGhvdyBtYW55IGFydGlzdHMgYXJlIGxpc3RlZCBpbiB0aGUgZGF0YS4gQWxzbywgaG93IG1hbnkgc29uZ3MgZWFjaCBhcnRpc3QgaGFzLgoKYGBge3J9CmFydGlzdDwtIGFzLmRhdGEuZnJhbWUodGFibGUoYXMuZGF0YS5mcmFtZShseXJpY3MkYXJ0aXN0KSkpCmNvbG5hbWVzKGFydGlzdCkgPC0gYygiYXJ0aXN0IiwgIk51bV9vZl9zb25ncyIpCmhlYWQoYXJ0aXN0KQpgYGAKCkxldCdzIHNlZSB0aGUgd2hpY2ggYXJ0aXN0IGhhcyBtb3N0IGFuZCBsZWFzdCBudW1iZXIgb2Ygc29uZ3MgaW4gdGhlIGRhdGFzZXQuCgpgYGB7cn0KbW9zdF9zb25ncyA8LSBhcnJhbmdlKGFydGlzdCwgZGVzYyhOdW1fb2Zfc29uZ3MpKQptb3N0X3NvbmdzCmBgYAoKYGBge3IgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9MywgZWNobz1GQUxTRX0KbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KFJtaXNjKQp0aWx0X3RoZW1lIDwtIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3Q9MSkpCnAxIDwtIGdncGxvdChkYXRhID0gaGVhZChtb3N0X3NvbmdzLDEwKSwgYWVzKGFydGlzdCwgTnVtX29mX3NvbmdzLCBmaWxsID0gTnVtX29mX3NvbmdzKSkgKwogICAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsPU51bV9vZl9zb25ncyksIHZqdXN0PTEuNiwgY29sb3I9IndoaXRlIiwgc2l6ZT0zKSArCiAgICAgIGdndGl0bGUoIkFydGlzdHMgd2l0aCBtb3N0IG51bWJlciBvZiBzb25ncyIpICsKICAgICAgdGlsdF90aGVtZQpwMQpgYGAKCmBgYHtyfQpsZWFzdF9zb25ncyA8LSB0YWlsKG1vc3Rfc29uZ3MsIDE1KQpwMiA8LSBnZ3Bsb3QoZGF0YSA9IGxlYXN0X3NvbmdzLCBhZXMoYXJ0aXN0LCBOdW1fb2Zfc29uZ3MsIGZpbGwgPSBOdW1fb2Zfc29uZ3MpKSArCiAgICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWw9TnVtX29mX3NvbmdzKSwgdmp1c3Q9MS42LCBjb2xvcj0id2hpdGUiLCBzaXplPTMpICsKICAgICAgZ2d0aXRsZSgiQXJ0aXN0cyB3aXRoIGxlYXN0IG51bWJlciBvZiBzb25ncyIpICsKICAgICAgdGlsdF90aGVtZQpwMgpgYGAKCkxldCdzIGNoZWNrIHRoZSBkaXN0cmlidXRpb24gb2Ygc29uZ3MgZm9yIGFsbCBhcnRpc3RzLgoKYGBge3J9CnAzIDwtIGdncGxvdChhcnRpc3QsIGFlcyh4PU51bV9vZl9zb25ncykpICsgCiBnZW9tX2hpc3RvZ3JhbShhZXMoeT0uLmRlbnNpdHkuLiksIGNvbG91cj0iYmxhY2siLCBmaWxsPSJ3aGl0ZSIpKwogZ2VvbV9kZW5zaXR5KGFscGhhPS4yLCBmaWxsPSJyZWQiKQpwMwpgYGAKCkxldCdzIGFuYWx5emUgdGhlIG51bWJlciBvZiB3b3JkcyBpbiBlYWNoIHNvbmcgYW5kIGl0cyBkaXN0cmlidXRpb24uCgpgYGB7cn0KbGlicmFyeShzdHJpbmdyKQpjb3VudF93b3JkcyA8LSBmdW5jdGlvbih2ZWMpewogIHJldHVybiAobGVuZ3RoKHVubGlzdCgoc3RyX2V4dHJhY3RfYWxsKHRvbG93ZXIodmVjKSwgJ1xcdysnKSkpKSkKfQpseXJpY3Mkd29yZF9jb3VudCA8LSBzYXBwbHkobHlyaWNzJHRleHQsIGNvdW50X3dvcmRzKQpoZWFkKGx5cmljcyR3b3JkX2NvdW50KQpgYGAKCmBgYHtyfQpwNCA8LSBnZ3Bsb3QobHlyaWNzLCBhZXMoeD13b3JkX2NvdW50KSkgKyAKIGdlb21faGlzdG9ncmFtKGFlcyh5PS4uZGVuc2l0eS4uKSwgY29sb3VyPSJibGFjayIsIGZpbGw9IndoaXRlIikrCiBnZW9tX2RlbnNpdHkoYWxwaGE9LjIsIGZpbGw9InJlZCIpCnA0CmBgYAoKTGV0J3MgYW5hbHl6ZSB0aGUgdGl0bGUgb2YgdGhlIHNvbmdzLCB0aGVpciB3b3JkY291bnQgYW5kIHRoZWlyIGRpc3RyaWJ1dGlvbgoKYGBge3J9Cmx5cmljcyR0aXRsZV93b3JkX2NvdW50IDwtIHNhcHBseShseXJpY3Mkc29uZywgY291bnRfd29yZHMpCmhlYWQobHlyaWNzJHRpdGxlX3dvcmRfY291bnQpCmBgYAoKTGV0J3MgY2hlY2sgb3V0IHRoZSBzb25ncyB0aGF0IGFyZSBsb25nZXN0IGFuZCBzaG9ydGVzdC4KCmBgYHtyfQpsb25nZXN0X3NvbmcgPC0gYXJyYW5nZShseXJpY3MsIGRlc2Mod29yZF9jb3VudCkpCmxvbmdlc3Rfc29uZyA8LSBoZWFkKGxvbmdlc3Rfc29uZywgMTApCnNob3J0ZXN0X3NvbmcgPC0gYXJyYW5nZShseXJpY3MsIHdvcmRfY291bnQpCnNob3J0ZXN0X3NvbmcgPC0gaGVhZChzaG9ydGVzdF9zb25nLCAxMCkKbG9uZ2VzdF9zb25nCnNob3J0ZXN0X3NvbmcKYGBgCgoKCmBgYHtyfQpwNSA8LSBnZ3Bsb3QoZGF0YSA9IGxvbmdlc3Rfc29uZywgYWVzKHNvbmcsIHdvcmRfY291bnQsIGZpbGwgPSB0aXRsZV93b3JkX2NvdW50KSkgKwogICAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsPXRpdGxlX3dvcmRfY291bnQpLCB2anVzdD0xLjYsIGNvbG9yPSJ3aGl0ZSIsIHNpemU9MykgKwogICAgICBnZ3RpdGxlKCJMb25nZXN0IFNvbmdzIikgKwogICAgICB0aWx0X3RoZW1lCnA2IDwtIGdncGxvdChkYXRhID0gc2hvcnRlc3Rfc29uZywgYWVzKHNvbmcsIHdvcmRfY291bnQsIGZpbGwgPSB0aXRsZV93b3JkX2NvdW50KSkgKwogICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSB0aXRsZV93b3JkX2NvdW50KSwgdmp1c3QgPSAxLjYsIGNvbG9yID0gIndoaXRlIiwgc2l6ZSA9IDMpICsKICAgICAgZ2d0aXRsZSgiU2hvcnRlc3QgU29uZ3MiKSArCiAgICAgIHRpbHRfdGhlbWUKbXVsdGlwbG90KHA1LCBwNiwgY29scz0yKQpgYGAKCgoKCmBgYHtyfQpwNyA8LSBnZ3Bsb3QobHlyaWNzLCBhZXMoeD10aXRsZV93b3JkX2NvdW50KSkgKyAKIGdlb21faGlzdG9ncmFtKGFlcyh5PS4uZGVuc2l0eS4uKSwgY29sb3VyPSJibGFjayIsIGZpbGw9IndoaXRlIiwgYmlud2lkdGggPSAxLCBiaW5zID0gMSkrCiBnZW9tX2RlbnNpdHkoYWxwaGE9LjIsIGZpbGw9InJlZCIpCnA3CmBgYAoKV29yZENsb3VkIG9mIHBvcHVsYXIgd29yZHMgZnJvbSBzb25nIHRpdGxlcwoKYGBge3J9CmxpYnJhcnkod29yZGNsb3VkKQpsaWJyYXJ5KFNub3diYWxsQykKbGlicmFyeShSQ29sb3JCcmV3ZXIpCmxpYnJhcnkodG0pCnRleHRzIDwtIGx5cmljcyRzb25nCiN0ZXh0cyA8LSBpY29udih0ZXh0cywgdG8gPSAidXRmLTgiKQpjb3JwdXMgPC0gQ29ycHVzKFZlY3RvclNvdXJjZSh0ZXh0cykpCmNvcnB1cyA8LSB0bV9tYXAoY29ycHVzLCBQbGFpblRleHREb2N1bWVudCkKY29ycHVzIDwtIHRtX21hcChjb3JwdXMsIHJlbW92ZVB1bmN0dWF0aW9uKQpjb3JwdXMgPC0gdG1fbWFwKGNvcnB1cywgcmVtb3ZlV29yZHMsIHN0b3B3b3JkcygnZW5nbGlzaCcpKQpjb3JwdXMgPC0gdG1fbWFwKGNvcnB1cywgc3RlbURvY3VtZW50KQpjb3JwdXMgPC0gdG1fbWFwKGNvcnB1cywgcmVtb3ZlV29yZHMsIGMoImFuZCIsICJ0aGlzIiwgInRoZXJlIikpIApjb3JwdXMgPC0gQ29ycHVzKFZlY3RvclNvdXJjZShjb3JwdXMpKQpkdG0gPC0gVGVybURvY3VtZW50TWF0cml4KGNvcnB1cykKbSA8LSBhcy5tYXRyaXgoZHRtKQp2IDwtIHNvcnQocm93U3VtcyhtKSxkZWNyZWFzaW5nPVRSVUUpCmQgPC0gZGF0YS5mcmFtZSh3b3JkID0gbmFtZXModiksZnJlcT12KQpoZWFkKGQsIDEwKQpkIDwtIGRbLXdoaWNoKGQkd29yZCAlaW4lIGMoImFuZCIsInRoaXMiLCJ0aGF0IikpLF0Kc2V0LnNlZWQoMTIzNCkKd29yZGNsb3VkKHdvcmRzID0gZCR3b3JkLCBmcmVxID0gZCRmcmVxLCBtaW4uZnJlcSA9IDEsCiAgICAgICAgICBtYXgud29yZHM9MjAwLCByYW5kb20ub3JkZXI9RkFMU0UsIHJvdC5wZXI9MC4zNSwgCiAgICAgICAgICBjb2xvcnM9YnJld2VyLnBhbCg4LCAiRGFyazIiKSkKYGBgCgpUaGVyZSBhcmUgbWFueSBzb25nIHRpdGxlcyB0aGF0IGFyZSBvZiBsZW5ndGggMSwgMiBhbmQgMy4gQnV0IHN1cnByaXNpbmdseSwgdGhlcmUgYXJlIHRpdGxlcyBvZiBsZW5ndGggbW9yZSB0aGFuIDEzIHRvby4gTGV0J3MgY2hlY2sgdGhlbSBvdXQuCgpgYGB7cn0KbG9uZ2VzdF90aXRsZSA8LSBzdWJzZXQobHlyaWNzLCBseXJpY3MkdGl0bGVfd29yZF9jb3VudCA+IDEzKQpsb25nZXN0X3RpdGxlCnNob3J0ZXN0X3RpdGxlIDwtIHN1YnNldChseXJpY3MsIGx5cmljcyR0aXRsZV93b3JkX2NvdW50ID09IDEpCnNob3J0ZXN0X3RpdGxlCmBgYAoKVGhlcmUgYXJlIDggc29uZ3Mgd2l0aCB0aXRsZSBsZW5ndGggbW9yZSB0aGFuIDEzIGFuZCA4MzQyIHNvbmdzIHdpdGggc2luZ2xlIHdvcmQgdGl0bGUuIExldCdzIHNlZSB3b3JkIGNsb3VkIG9mIHNpbmdsZSB3b3JkIHRpdGxlcyBhbmQgbG9uZ2VzdCB0aXRsZXMKCmBgYHtyfQp0ZXh0cyA8LSBsb25nZXN0X3RpdGxlJHNvbmcKY29ycHVzIDwtIENvcnB1cyhWZWN0b3JTb3VyY2UodGV4dHMpKQpjb3JwdXMgPC0gdG1fbWFwKGNvcnB1cywgUGxhaW5UZXh0RG9jdW1lbnQpCmNvcnB1cyA8LSBDb3JwdXMoVmVjdG9yU291cmNlKGNvcnB1cykpCmR0bSA8LSBUZXJtRG9jdW1lbnRNYXRyaXgoY29ycHVzKQptIDwtIGFzLm1hdHJpeChkdG0pCnYgPC0gc29ydChyb3dTdW1zKG0pLGRlY3JlYXNpbmc9VFJVRSkKZCA8LSBkYXRhLmZyYW1lKHdvcmQgPSBuYW1lcyh2KSxmcmVxPXYpCmhlYWQoZCwgMTApCnNldC5zZWVkKDEyMzQpCndvcmRjbG91ZCh3b3JkcyA9IGQkd29yZCwgZnJlcSA9IGQkZnJlcSwgbWluLmZyZXEgPSAxLHNjYWxlPWMoMiwwLjUpLAogICAgICAgICAgbWF4LndvcmRzPTEwMCwgcmFuZG9tLm9yZGVyPUZBTFNFLCByb3QucGVyPTAuMzUsIAogICAgICAgICAgY29sb3JzPWJyZXdlci5wYWwoOCwgIkRhcmsyIikpCmBgYAoKYGBge3J9CnRleHRzIDwtIHNob3J0ZXN0X3RpdGxlJHNvbmcKY29ycHVzIDwtIENvcnB1cyhWZWN0b3JTb3VyY2UodGV4dHMpKQpjb3JwdXMgPC0gdG1fbWFwKGNvcnB1cywgUGxhaW5UZXh0RG9jdW1lbnQpCmNvcnB1cyA8LSBDb3JwdXMoVmVjdG9yU291cmNlKGNvcnB1cykpCmR0bSA8LSBUZXJtRG9jdW1lbnRNYXRyaXgoY29ycHVzKQptIDwtIGFzLm1hdHJpeChkdG0pCnYgPC0gc29ydChyb3dTdW1zKG0pLGRlY3JlYXNpbmc9VFJVRSkKZCA8LSBkYXRhLmZyYW1lKHdvcmQgPSBuYW1lcyh2KSxmcmVxPXYpCmhlYWQoZCwgMTApCnNldC5zZWVkKDEyMzQpCndvcmRjbG91ZCh3b3JkcyA9IGQkd29yZCwgZnJlcSA9IGQkZnJlcSwgbWluLmZyZXEgPSAxLHNjYWxlPWMoMiwwLjUpLAogICAgICAgICAgbWF4LndvcmRzPTEwMCwgcmFuZG9tLm9yZGVyPUZBTFNFLCByb3QucGVyPTAuMzUsIAogICAgICAgICAgY29sb3JzPWJyZXdlci5wYWwoOCwgIkRhcmsyIikpCmBgYAoKQW4gaW50ZXJlc3RpbmcgcXVlc3RpbiB3b3VsZCBiZSBpcyB0aGVyZSByZWxhdGlvbiBiZXR3ZWVuIGxlbmd0aCBvZiB0aXRsZSBhbmQgc29uZ3M/IE1vc3QgcHJvYmFibHkgbm93LCBidXQgbGV0J3MgY2hlY2sgb3V0LgoKYGBge3J9CnA4IDwtIGdncGxvdChseXJpY3MsIGFlcyh4PWZhY3Rvcih0aXRsZV93b3JkX2NvdW50KSwgeT13b3JkX2NvdW50LCBmaWxsID0gZmFjdG9yKHRpdGxlX3dvcmRfY291bnQpKSkgKyAKICBnZW9tX2JveHBsb3QoKSAKcDggCmBgYAoKYGBge3J9CmNvcihseXJpY3MkdGl0bGVfd29yZF9jb3VudCwgbHlyaWNzJHdvcmRfY291bnQpCmBgYAogQXMgZXhwZWN0ZWQsIHRoZXJlIGlzIG5vIGNvcnJlbGF0aW9uIGJldHdlZW4gdGhlc2UgdHdvIHF1YW50aXRpdGVzLgogCiBMZXQgdXMgZml4IHRoZSBjb250cmFjdGVkIHdvcmRzIHRvIHRoZWlyIGZ1bGwgZm9ybXMgZmlyc3QuCgpgYGB7cn0KIyBmdW5jdGlvbiB0byBleHBhbmQgY29udHJhY3Rpb25zIGluIGFuIEVuZ2xpc2gtbGFuZ3VhZ2Ugc291cmNlCmZpeC5jb250cmFjdGlvbnMgPC0gZnVuY3Rpb24oZG9jKSB7CiAgIyAid29uJ3QiIGlzIGEgc3BlY2lhbCBjYXNlIGFzIGl0IGRvZXMgbm90IGV4cGFuZCB0byAid28gbm90IgogIGRvYyA8LSBnc3ViKCJ3b24ndCIsICJ3aWxsIG5vdCIsIGRvYykKICBkb2MgPC0gZ3N1YigiY2FuJ3QiLCAiY2FuIG5vdCIsIGRvYykKICBkb2MgPC0gZ3N1Yigibid0IiwgIiBub3QiLCBkb2MpCiAgZG9jIDwtIGdzdWIoIidsbCIsICIgd2lsbCIsIGRvYykKICBkb2MgPC0gZ3N1YigiJ3JlIiwgIiBhcmUiLCBkb2MpCiAgZG9jIDwtIGdzdWIoIid2ZSIsICIgaGF2ZSIsIGRvYykKICBkb2MgPC0gZ3N1YigiJ20iLCAiIGFtIiwgZG9jKQogIGRvYyA8LSBnc3ViKCInZCIsICIgd291bGQiLCBkb2MpCiAgIyAncyBjb3VsZCBiZSAnaXMnIG9yIGNvdWxkIGJlIHBvc3Nlc3NpdmU6IGl0IGhhcyBubyBleHBhbnNpb24KICBkb2MgPC0gZ3N1YigiJ3MiLCAiIiwgZG9jKQogIHJldHVybihkb2MpCn0KCiMgZml4IChleHBhbmQpIGNvbnRyYWN0aW9ucwpseXJpY3MkdGV4dCA8LSBzYXBwbHkobHlyaWNzJHRleHQsIGZpeC5jb250cmFjdGlvbnMpCmBgYAogCiBSZW1vdmUgc3BlY2lhbCBjaGFyYWN0ZXJzIGZyb20gbHlyaWNzCmBgYHtyfQojIGZ1bmN0aW9uIHRvIHJlbW92ZSBzcGVjaWFsIGNoYXJhY3RlcnMKcmVtb3ZlU3BlY2lhbENoYXJzIDwtIGZ1bmN0aW9uKHgpIGdzdWIoIlteYS16QS1aMC05IF0iLCAiICIsIHgpCiMgcmVtb3ZlIHNwZWNpYWwgY2hhcmFjdGVycwpseXJpY3MkdGV4dCA8LSBzYXBwbHkobHlyaWNzJHRleHQsIHJlbW92ZVNwZWNpYWxDaGFycykKYGBgCgpDb252ZXJ0IGFsbCBseXJpY3MgdGV4dCB0byBsb3dlciBjYXNlCmBgYHtyfQojIGNvbnZlcnQgZXZlcnl0aGluZyB0byBsb3dlciBjYXNlCmx5cmljcyR0ZXh0IDwtIHNhcHBseShseXJpY3MkdGV4dCwgdG9sb3dlcikKYGBgCgpMZXQncyBjaGVjayB0aGUgc3RydWN0dXJlIG9mIG9uZSBseXJpY3MgdG8gc2VlIHRoZSBjaGFuZ2VzLgpgYGB7cn0Kc3RyKGx5cmljc1sxMywgXSR0ZXh0LCBuY2hhci5tYXggPSAzMDApCmBgYAogCiBTRU5USU1FTlQgQU5BTFlTSVMgT0YgTFlSSUNTCiBMZXQgdXMgcGVyZm9ybSBzZW50aW1lbnQgYW5hbHlzaXMgb24gdGhlIGx5cmljcy4gVGhlcmUgYXJlIHZhcmlvdXMgdHlwZXMgb2Ygc2VudGltZW50IGxleGljb25zIHRoYXQgY2FuIGJlIHVzZWQuIExldHMgdXMgaGF2ZSBhIGxvb2sgb24gdGhlbS4KYGBge3J9CmxpYnJhcnkodGlkeXRleHQpCmxpYnJhcnkodGlkeXIpCmdldF9zZW50aW1lbnRzKCJhZmlubiIpCmdldF9zZW50aW1lbnRzKCJiaW5nIikKZ2V0X3NlbnRpbWVudHMoIm5yYyIpCmdldF9zZW50aW1lbnRzKCJsb3VnaHJhbiIpCmBgYAoKbnJjIHNlZW1zIHRvIGhhdmUgbGFyZ2UgbnVtYmVyIG9mIHdvcmRzIGFuZCB0aGVpciBzZW50aW1lbnRzIGNvbXBhcmVkIHRvIG90aGVyIHR3by4KCmBgYHtyfQpucmNfc2VudGltZW50IDwtIGdldF9zZW50aW1lbnRzKCJucmMiKQp1bmlxdWUobnJjX3NlbnRpbWVudCRzZW50aW1lbnQpCmBgYAoKTGV0IHVzIGZpbmQgdGhlIHNlbnRpbWVudHMgb2YgZWFjaCBseXJpY3MgYmFzZWQgb24gZWFjaCBOUkMgc2VudGltZW50cy4KCmBgYHtyfQpseXJpY3Nfd29yZHMgPC0gc2VsZWN0KGx5cmljcywgYygiYXJ0aXN0IiwgInRleHQiKSkKbHlyaWNzX3dvcmRzIDwtIGx5cmljc193b3JkcyAlPiUgdW5uZXN0X3Rva2Vucyh3b3JkLCB0ZXh0KQpoZWFkKGx5cmljc193b3JkcykKZGltKGx5cmljc193b3JkcykKYGBgCgpMZXQncyBzZWUgd29yZHMgdGhhdCBkZXBpY3QgImpveSIKYGBge3J9CmpveSA8LSBseXJpY3Nfd29yZHMgJT4lCiAgaW5uZXJfam9pbihnZXRfc2VudGltZW50cygibnJjIikgJT4lIAogIGZpbHRlcihzZW50aW1lbnQgPT0gImpveSIpKSAKam95IDwtIGFzLmRhdGEuZnJhbWUoc29ydCh0YWJsZShqb3kkd29yZCkpKQpjb2x1bW5zX3NlbnRpbWVudCA8LSBjKCJ3b3JkIiwgIkZyZXEiKQpjb2xuYW1lcyhqb3kpIDwtIGNvbHVtbnNfc2VudGltZW50CnRhaWwoam95LCAxMCkKCmBgYAoKU2ltaWxhcmx5LCBsZXQncyBzZWUgb3RoZXIgd29yZHMgdGhhdCByZXByZXNlbnRzIG90aGVyIDkgc2VudGltZW50cy4KCmBgYHtyfQp0cnVzdCA8LSBseXJpY3Nfd29yZHMgJT4lCiAgaW5uZXJfam9pbihnZXRfc2VudGltZW50cygibnJjIikgJT4lIAogIGZpbHRlcihzZW50aW1lbnQgPT0gInRydXN0IikpIAp0cnVzdCA8LSBhcy5kYXRhLmZyYW1lKHNvcnQodGFibGUodHJ1c3Qkd29yZCkpKQpjb2xuYW1lcyh0cnVzdCkgPC0gY29sdW1uc19zZW50aW1lbnQKdGFpbCh0cnVzdCwgMTApCmBgYAoKYGBge3J9CmZlYXIgPC0gbHlyaWNzX3dvcmRzICU+JQogIGlubmVyX2pvaW4oZ2V0X3NlbnRpbWVudHMoIm5yYyIpICU+JSAKICBmaWx0ZXIoc2VudGltZW50ID09ICJmZWFyIikpIApmZWFyIDwtIGFzLmRhdGEuZnJhbWUoc29ydCh0YWJsZShmZWFyJHdvcmQpKSkKY29sbmFtZXMoZmVhcikgPC0gY29sdW1uc19zZW50aW1lbnQKCnNhZG5lc3MgPC0gbHlyaWNzX3dvcmRzICU+JQogIGlubmVyX2pvaW4oZ2V0X3NlbnRpbWVudHMoIm5yYyIpICU+JSAKICBmaWx0ZXIoc2VudGltZW50ID09ICJzYWRuZXNzIikpIApzYWRuZXNzIDwtIGFzLmRhdGEuZnJhbWUoc29ydCh0YWJsZShzYWRuZXNzJHdvcmQpKSkKY29sbmFtZXMoc2FkbmVzcykgPC0gY29sdW1uc19zZW50aW1lbnQKCmFuZ2VyIDwtIGx5cmljc193b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJucmMiKSAlPiUgCiAgZmlsdGVyKHNlbnRpbWVudCA9PSAiYW5nZXIiKSkgCmFuZ2VyIDwtIGFzLmRhdGEuZnJhbWUoc29ydCh0YWJsZShhbmdlciR3b3JkKSkpCmNvbG5hbWVzKGFuZ2VyKSA8LSBjb2x1bW5zX3NlbnRpbWVudAoKc3VycHJpc2UgPC0gbHlyaWNzX3dvcmRzICU+JQogIGlubmVyX2pvaW4oZ2V0X3NlbnRpbWVudHMoIm5yYyIpICU+JSAKICBmaWx0ZXIoc2VudGltZW50ID09ICJzdXJwcmlzZSIpKSAKc3VycHJpc2UgPC0gYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKHN1cnByaXNlJHdvcmQpKSkKY29sbmFtZXMoc3VycHJpc2UpIDwtIGNvbHVtbnNfc2VudGltZW50CgpkaXNndXN0IDwtIGx5cmljc193b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJucmMiKSAlPiUgCiAgZmlsdGVyKHNlbnRpbWVudCA9PSAiZGlzZ3VzdCIpKSAKZGlzZ3VzdCA8LSBhcy5kYXRhLmZyYW1lKHNvcnQodGFibGUoZGlzZ3VzdCR3b3JkKSkpCmNvbG5hbWVzKGRpc2d1c3QpIDwtIGNvbHVtbnNfc2VudGltZW50CgphbnRpY2lwYXRpb24gPC0gbHlyaWNzX3dvcmRzICU+JQogIGlubmVyX2pvaW4oZ2V0X3NlbnRpbWVudHMoIm5yYyIpICU+JSAKICBmaWx0ZXIoc2VudGltZW50ID09ICJhbnRpY2lwYXRpb24iKSkgCmFudGljaXBhdGlvbiA8LSBhcy5kYXRhLmZyYW1lKHNvcnQodGFibGUoYW50aWNpcGF0aW9uJHdvcmQpKSkKY29sbmFtZXMoYW50aWNpcGF0aW9uKSA8LSBjb2x1bW5zX3NlbnRpbWVudApgYGAKCkxldCdzIHBsb3QgdGhlIHdvcmQgb2NjdXJlbmNlcyBmb3IgZWFjaCBzZW50aW1lbnQgKGV4Y2VwdCBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUpCgpgYGB7ciBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD00LCBlY2hvPUZBTFNFfQpwOSA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwoam95LCAxMCksIGFlcyh3b3JkLCBGcmVxLCBmaWxsID0gd29yZCkpICsKICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gRnJlcSksIHZqdXN0ID0gMS42LCBjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSAzKSArCiAgICAgIGdndGl0bGUoIkpveSIpICsKICAgICAgZ3VpZGVzKGZpbGw9RkFMU0UpICsKICAgICAgdGlsdF90aGVtZQpwMTAgPC0gZ2dwbG90KGRhdGEgPSB0YWlsKHRydXN0LCAxMCksIGFlcyh3b3JkLCBGcmVxLCBmaWxsID0gd29yZCkpICsKICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gRnJlcSksIHZqdXN0ID0gMS42LCBjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSAzKSArCiAgICAgIGdndGl0bGUoIlRydXN0IikgKwogICAgICBndWlkZXMoZmlsbD1GQUxTRSkgKwogICAgICB0aWx0X3RoZW1lCnAxMSA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwoZmVhciwgMTApLCBhZXMod29yZCwgRnJlcSwgZmlsbCA9IHdvcmQpKSArCiAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLCB2anVzdCA9IDEuNiwgY29sb3IgPSAid2hpdGUiLCBzaXplID0gMykgKwogICAgICBnZ3RpdGxlKCJGZWFyIikgKwogICAgICBndWlkZXMoZmlsbD1GQUxTRSkgKwogICAgICB0aWx0X3RoZW1lCnAxMiA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwoc2FkbmVzcywgMTApLCBhZXMod29yZCwgRnJlcSwgZmlsbCA9IHdvcmQpKSArCiAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLCB2anVzdCA9IDEuNiwgY29sb3IgPSAid2hpdGUiLCBzaXplID0gMykgKwogICAgICBnZ3RpdGxlKCJTYWRuZXNzIikgKwogICAgICBndWlkZXMoZmlsbD1GQUxTRSkgKwogICAgICB0aWx0X3RoZW1lCnAxMyA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwoYW5nZXIsIDEwKSwgYWVzKHdvcmQsIEZyZXEsIGZpbGwgPSB3b3JkKSkgKwogICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVxKSwgdmp1c3QgPSAxLjYsIGNvbG9yID0gIndoaXRlIiwgc2l6ZSA9IDMpICsKICAgICAgZ2d0aXRsZSgiQW5nZXIiKSArCiAgICAgIGd1aWRlcyhmaWxsPUZBTFNFKSArCiAgICAgIHRpbHRfdGhlbWUKcDE0IDwtIGdncGxvdChkYXRhID0gdGFpbChzdXJwcmlzZSwgMTApLCBhZXMod29yZCwgRnJlcSwgZmlsbCA9IHdvcmQpKSArCiAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLCB2anVzdCA9IDEuNiwgY29sb3IgPSAid2hpdGUiLCBzaXplID0gMykgKwogICAgICBnZ3RpdGxlKCJTdXJwcmlzZSIpICsKICAgICAgZ3VpZGVzKGZpbGw9RkFMU0UpICsKICAgICAgdGlsdF90aGVtZQpwMTUgPC0gZ2dwbG90KGRhdGEgPSB0YWlsKGRpc2d1c3QsIDEwKSwgYWVzKHdvcmQsIEZyZXEsIGZpbGwgPSB3b3JkKSkgKwogICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVxKSwgdmp1c3QgPSAxLjYsIGNvbG9yID0gIndoaXRlIiwgc2l6ZSA9IDMpICsKICAgICAgZ2d0aXRsZSgiRGlzZ3VzdCIpICsKICAgICAgZ3VpZGVzKGZpbGw9RkFMU0UpICsKICAgICAgdGlsdF90aGVtZQpwMTYgPC0gZ2dwbG90KGRhdGEgPSB0YWlsKGFudGljaXBhdGlvbiwgMTApLCBhZXMod29yZCwgRnJlcSwgZmlsbCA9IHdvcmQpKSArCiAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLCB2anVzdCA9IDEuNiwgY29sb3IgPSAid2hpdGUiLCBzaXplID0gMykgKwogICAgICBnZ3RpdGxlKCJBbnRpY2lwYXRpb24iKSArCiAgICAgIGd1aWRlcyhmaWxsPUZBTFNFKSArCiAgICAgIHRpbHRfdGhlbWUKCm11bHRpcGxvdChwOSwgcDEwLCBwMTEsIHAxMiwgcDEzLCBwMTQsIHAxNSwgcDE2LCBsYXlvdXQgPSBtYXRyaXgoYygxLDIsMyw0LDUsNiw3LDgpLCBucm93PTIsIGJ5cm93PVRSVUUpKQoKCmBgYAoKTGV0J3MgcGxvdCB0aGUgd29yZGNsb3VkIGZvciBlYWNoIGNhdGVnb3J5CgpgYGB7ciBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD04LCBlY2hvPUZBTFNFfQoKI0NyZWF0ZSB0d28gcGFuZWxzIHRvIGFkZCB0aGUgd29yZCBjbG91ZHMgdG8KcGFyKG1mcm93PWMoNCwyKSkKCndvcmRjbG91ZCh3b3JkcyA9IGpveSR3b3JkLCBmcmVxID0gam95JEZyZXEsIG1pbi5mcmVxID0gNTAsCiAgICAgICAgICBtYXgud29yZHM9MTAwLCBzY2FsZT1jKDIsIDEpLCByYW5kb20ub3JkZXIgPSBGQUxTRSwgcmFuZG9tLmNvbG9yID0gRkFMU0UsIHJvdC5wZXI9MC4zNSwgCiAgICAgICAgICBjb2xvcnM9YnJld2VyLnBhbCg4LCAiRGFyazIiKSkKdGl0bGUoIkpveSB3b3JkcyIsIG91dGVyPUZBTFNFKQogICAgICAgICAgI2NvbG9ycz0gYygiaW5kaWFucmVkMSIsImluZGlhbnJlZDIiLCJpbmRpYW5yZWQzIiwiaW5kaWFucmVkIikpCgp3b3JkY2xvdWQod29yZHMgPSB0cnVzdCR3b3JkLCBmcmVxID0gdHJ1c3QkRnJlcSwgbWluLmZyZXEgPSA1MCwKICAgICAgICAgIG1heC53b3Jkcz0xMDAsIHNjYWxlPWMoMiwgMSksIHJhbmRvbS5vcmRlciA9IEZBTFNFLCByYW5kb20uY29sb3IgPSBGQUxTRSwgcm90LnBlcj0wLjM1LCAKICAgICAgICAgIGNvbG9ycz1icmV3ZXIucGFsKDgsICJEYXJrMiIpKQp0aXRsZSgiVHJ1c3Qgd29yZHMiLCBvdXRlcj1GQUxTRSkKCndvcmRjbG91ZCh3b3JkcyA9IGZlYXIkd29yZCwgZnJlcSA9IGZlYXIkRnJlcSwgbWluLmZyZXEgPSA1MCwKICAgICAgICAgIG1heC53b3Jkcz0xMDAsIHNjYWxlPWMoMiwgMSksIHJhbmRvbS5vcmRlciA9IEZBTFNFLCByYW5kb20uY29sb3IgPSBGQUxTRSwgcm90LnBlcj0wLjM1LCAKICAgICAgICAgIGNvbG9ycz1icmV3ZXIucGFsKDgsICJEYXJrMiIpKQp0aXRsZSgiRmVhciB3b3JkcyIsIG91dGVyPUZBTFNFKQoKd29yZGNsb3VkKHdvcmRzID0gc2FkbmVzcyR3b3JkLCBmcmVxID0gc2FkbmVzcyRGcmVxLCBtaW4uZnJlcSA9IDUwLAogICAgICAgICAgbWF4LndvcmRzPTEwMCwgc2NhbGU9YygyLCAxKSwgcmFuZG9tLm9yZGVyID0gRkFMU0UsIHJhbmRvbS5jb2xvciA9IEZBTFNFLCByb3QucGVyPTAuMzUsIAogICAgICAgICAgY29sb3JzPWJyZXdlci5wYWwoOCwgIkRhcmsyIikpCnRpdGxlKCJTYWRuZXNzIHdvcmRzIiwgb3V0ZXI9RkFMU0UpCgp3b3JkY2xvdWQod29yZHMgPSBhbmdlciR3b3JkLCBmcmVxID0gYW5nZXIkRnJlcSwgbWluLmZyZXEgPSA1MCwKICAgICAgICAgIG1heC53b3Jkcz0xMDAsIHNjYWxlPWMoMiwgMSksIHJhbmRvbS5vcmRlciA9IEZBTFNFLCByYW5kb20uY29sb3IgPSBGQUxTRSwgcm90LnBlcj0wLjM1LCAKICAgICAgICAgIGNvbG9ycz1icmV3ZXIucGFsKDgsICJEYXJrMiIpKQp0aXRsZSgiQW5nZXIgd29yZHMiLCBvdXRlcj1GQUxTRSkKCndvcmRjbG91ZCh3b3JkcyA9IHN1cnByaXNlJHdvcmQsIGZyZXEgPSBzdXJwcmlzZSRGcmVxLCBtaW4uZnJlcSA9IDUwLAogICAgICAgICAgbWF4LndvcmRzPTEwMCwgc2NhbGU9YygyLCAxKSwgcmFuZG9tLm9yZGVyID0gRkFMU0UsIHJhbmRvbS5jb2xvciA9IEZBTFNFLCByb3QucGVyPTAuMzUsIAogICAgICAgICAgY29sb3JzPWJyZXdlci5wYWwoOCwgIkRhcmsyIikpCnRpdGxlKCJTdXJwcmlzZSB3b3JkcyIsIG91dGVyPUZBTFNFKQoKd29yZGNsb3VkKHdvcmRzID0gZGlzZ3VzdCR3b3JkLCBmcmVxID0gZGlzZ3VzdCRGcmVxLCBtaW4uZnJlcSA9IDUwLAogICAgICAgICAgbWF4LndvcmRzPTEwMCwgc2NhbGU9YygyLCAxKSwgcmFuZG9tLm9yZGVyID0gRkFMU0UsIHJhbmRvbS5jb2xvciA9IEZBTFNFLCByb3QucGVyPTAuMzUsIAogICAgICAgICAgY29sb3JzPWJyZXdlci5wYWwoOCwgIkRhcmsyIikpCnRpdGxlKCJEaXNndXN0IHdvcmRzIiwgb3V0ZXI9RkFMU0UpCgp3b3JkY2xvdWQod29yZHMgPSBhbnRpY2lwYXRpb24kd29yZCwgZnJlcSA9IGFudGljaXBhdGlvbiRGcmVxLCBtaW4uZnJlcSA9IDUwLAogICAgICAgICAgbWF4LndvcmRzPTEwMCwgc2NhbGU9YygyLCAxKSwgcmFuZG9tLm9yZGVyID0gRkFMU0UsIHJhbmRvbS5jb2xvciA9IEZBTFNFLCByb3QucGVyPTAuMzUsIAogICAgICAgICAgY29sb3JzPWJyZXdlci5wYWwoOCwgIkRhcmsyIikpCnRpdGxlKCJBbnRpY2lwYXRpb24gd29yZHMiLCBvdXRlcj1GQUxTRSkKYGBgCgpMZXQgdXMgY2hlY2sgdG9wIHdvcmRzIHRoYXQgZGVwaWN0cyAicG9zaXRpdmUiIGFuZCAibmVnYXRpdmUiIHNlbnRpbWVudHMgaW4gTlJDIFNlbnRpbWVudCBjYXRlZ29yeS4KCmBgYHtyIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTIsIGVjaG89RkFMU0V9CnBvcyA8LSBseXJpY3Nfd29yZHMgJT4lCiAgaW5uZXJfam9pbihnZXRfc2VudGltZW50cygibnJjIikgJT4lIAogIGZpbHRlcihzZW50aW1lbnQgPT0gInBvc2l0aXZlIikpIApwb3MgPC0gYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKHBvcyR3b3JkKSkpCmNvbG5hbWVzKHBvcykgPC0gY29sdW1uc19zZW50aW1lbnQKCm5lZyA8LSBseXJpY3Nfd29yZHMgJT4lCiAgaW5uZXJfam9pbihnZXRfc2VudGltZW50cygibnJjIikgJT4lIAogIGZpbHRlcihzZW50aW1lbnQgPT0gIm5lZ2F0aXZlIikpIApuZWcgPC0gYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKG5lZyR3b3JkKSkpCmNvbG5hbWVzKG5lZykgPC0gY29sdW1uc19zZW50aW1lbnQKCnAxNyA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwocG9zLCAyMCksIGFlcyh3b3JkLCBGcmVxLCBmaWxsID0gd29yZCkpICsKICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gRnJlcSksIHZqdXN0ID0gMS42LCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzLCBhbmdsZT05MCkgKwogICAgICBnZ3RpdGxlKCJQb3NpdGl2ZSAoTlJDKSIpICsKICAgICAgZ3VpZGVzKGZpbGw9RkFMU0UpICsKICAgICAgdGlsdF90aGVtZQpwMTggPC0gZ2dwbG90KGRhdGEgPSB0YWlsKG5lZywgMjApLCBhZXMod29yZCwgRnJlcSwgZmlsbCA9IHdvcmQpKSArCiAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLCB2anVzdCA9IDEuNiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMywgYW5nbGU9OTApICsKICAgICAgZ2d0aXRsZSgiTmVnYXRpdmUgKE5SQykiKSArCiAgICAgIGd1aWRlcyhmaWxsPUZBTFNFKSArCiAgICAgIHRpbHRfdGhlbWUKbXVsdGlwbG90KHAxNywgcDE4LCBjb2xzPTIpCmBgYAoKCgoKTGV0IHVzIGNoZWNrIHRvcCB3b3JkcyB0aGF0IGRlcGljdHMgInBvc2l0aXZlIiBhbmQgIm5lZ2F0aXZlIiBzZW50aW1lbnRzIGluIGJpbmcgU2VudGltZW50IGNhdGVnb3J5LgoKYGBge3IgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTUsIGVjaG89RkFMU0V9CnBvc19iIDwtIGx5cmljc193b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJiaW5nIikgJT4lIAogIGZpbHRlcihzZW50aW1lbnQgPT0gInBvc2l0aXZlIikpIApwb3NfYiA8LSBhcy5kYXRhLmZyYW1lKHNvcnQodGFibGUocG9zX2Ikd29yZCkpKQpjb2xuYW1lcyhwb3NfYikgPC0gY29sdW1uc19zZW50aW1lbnQKCm5lZ19iIDwtIGx5cmljc193b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJiaW5nIikgJT4lIAogIGZpbHRlcihzZW50aW1lbnQgPT0gIm5lZ2F0aXZlIikpIApuZWdfYiA8LSBhcy5kYXRhLmZyYW1lKHNvcnQodGFibGUobmVnX2Ikd29yZCkpKQpjb2xuYW1lcyhuZWdfYikgPC0gY29sdW1uc19zZW50aW1lbnQKCnBvc19sIDwtIGx5cmljc193b3JkcyAlPiUgCiAgaW5uZXJfam9pbihnZXRfc2VudGltZW50cygibG91Z2hyYW4iKSAlPiUgCiAgZmlsdGVyKHNlbnRpbWVudCA9PSAicG9zaXRpdmUiKSkgCnBvc19sIDwtIGFzLmRhdGEuZnJhbWUoc29ydCh0YWJsZShwb3NfbCR3b3JkKSkpCmNvbG5hbWVzKHBvc19sKSA8LSBjb2x1bW5zX3NlbnRpbWVudAoKbmVnX2wgPC0gbHlyaWNzX3dvcmRzICU+JQogIGlubmVyX2pvaW4oZ2V0X3NlbnRpbWVudHMoImxvdWdocmFuIikgJT4lIAogIGZpbHRlcihzZW50aW1lbnQgPT0gIm5lZ2F0aXZlIikpIApuZWdfbCA8LSBhcy5kYXRhLmZyYW1lKHNvcnQodGFibGUobmVnX2wkd29yZCkpKQpjb2xuYW1lcyhuZWdfbCkgPC0gY29sdW1uc19zZW50aW1lbnQKCnAxOSA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwocG9zX2IsIDIwKSwgYWVzKHdvcmQsIEZyZXEsIGZpbGwgPSB3b3JkKSkgKwogICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVxKSwgdmp1c3QgPSAxLjYsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMsIGFuZ2xlPTkwKSArCiAgICAgIGdndGl0bGUoIlBvc2l0aXZlIChCSU5HKSIpICsKICAgICAgZ3VpZGVzKGZpbGw9RkFMU0UpICsKICAgICAgdGlsdF90aGVtZQpwMjAgPC0gZ2dwbG90KGRhdGEgPSB0YWlsKG5lZ19iLCAyMCksIGFlcyh3b3JkLCBGcmVxLCBmaWxsID0gd29yZCkpICsKICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gRnJlcSksIHZqdXN0ID0gMS42LCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzLCBhbmdsZT05MCkgKwogICAgICBnZ3RpdGxlKCJOZWdhdGl2ZSAoQklORykiKSArCiAgICAgIGd1aWRlcyhmaWxsPUZBTFNFKSArCiAgICAgIHRpbHRfdGhlbWUKcDIxIDwtIGdncGxvdChkYXRhID0gdGFpbChwb3NfbCwgMjApLCBhZXMod29yZCwgRnJlcSwgZmlsbCA9IHdvcmQpKSArCiAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLCB2anVzdCA9IDEuNiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMywgYW5nbGU9OTApICsKICAgICAgZ2d0aXRsZSgiUG9zaXRpdmUgKExPVUdIUkFOKSIpICsKICAgICAgZ3VpZGVzKGZpbGw9RkFMU0UpICsKICAgICAgdGlsdF90aGVtZQpwMjIgPC0gZ2dwbG90KGRhdGEgPSB0YWlsKG5lZ19sLCAyMCksIGFlcyh3b3JkLCBGcmVxLCBmaWxsID0gd29yZCkpICsKICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gRnJlcSksIHZqdXN0ID0gMS42LCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzLCBhbmdsZT05MCkgKwogICAgICBnZ3RpdGxlKCJOZWdhdGl2ZSAoTE9VR0hSQU4pIikgKwogICAgICBndWlkZXMoZmlsbD1GQUxTRSkgKwogICAgICB0aWx0X3RoZW1lCm11bHRpcGxvdChwMTksIHAyMCxwMjEsIHAyMixsYXlvdXQgPSBtYXRyaXgoYygxLDIsMyw0KSwgbnJvdz0yLCBieXJvdz1UUlVFKSkKCmBgYAoKSXQgY2FuIGJlIHNlZW4gdGhhdCBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUgd29yZHMgYXJlIGRpZmZlcmVudCBmb3IgYWxsIHRocmVlIGxleGljb25zLiAKCkxldCdzIHBsb3QgcG9zaXRpdmUgYW5kIG5lZ2F0aXZlIHdvcmQgY2xvdWQKCgpgYGB7ciBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD03LCBlY2hvPUZBTFNFfQoKI0NyZWF0ZSB0d28gcGFuZWxzIHRvIGFkZCB0aGUgd29yZCBjbG91ZHMgdG8KcGFyKG1mcm93PWMoMywyKSkKI0NyZWF0ZSB3b3JkIGNsb3VkIG9mIHBvc2l0aXZlIHdvcmRzIG9mIE5SQyBsZXhpY29uCndvcmRjbG91ZCh3b3JkcyA9IHBvcyR3b3JkLCBmcmVxID0gcG9zJEZyZXEsIG1pbi5mcmVxID0gNTAsCiAgICAgICAgICBtYXgud29yZHM9MTAwLCBzY2FsZT1jKDIsIDEpLCByYW5kb20ub3JkZXIgPSBGQUxTRSwgcmFuZG9tLmNvbG9yID0gRkFMU0UsIHJvdC5wZXI9MC4zNSwgCiAgICAgICAgICBjb2xvcnM9YnJld2VyLnBhbCg4LCAiRGFyazIiKSkKdGl0bGUoIlBvc2l0aXZlIHdvcmRzIGluIE5SQyBMZXhpY29uIiwgb3V0ZXI9RkFMU0UpCiAgICAgICAgICAjY29sb3JzPSBjKCJpbmRpYW5yZWQxIiwiaW5kaWFucmVkMiIsImluZGlhbnJlZDMiLCJpbmRpYW5yZWQiKSkKI0NyZWF0ZSB3b3JkIGNsb3VkIG9mIG5lZ2F0aXZlIHdvcmRzIG9mIE5SQyBsZXhpY29uCndvcmRjbG91ZCh3b3JkcyA9IG5lZyR3b3JkLCBmcmVxID0gbmVnJEZyZXEsIG1pbi5mcmVxID0gNTAsCiAgICAgICAgICBtYXgud29yZHM9MTAwLCBzY2FsZT1jKDIsIDEpLCByYW5kb20ub3JkZXIgPSBGQUxTRSwgcmFuZG9tLmNvbG9yID0gRkFMU0UsIHJvdC5wZXI9MC4zNSwgCiAgICAgICAgICBjb2xvcnM9YnJld2VyLnBhbCg4LCAiQWNjZW50IikpCnRpdGxlKCJOZWdhdGl2ZSB3b3JkcyBpbiBOUkMgTGV4aWNvbiIsIG91dGVyPUZBTFNFKQojQ3JlYXRlIHdvcmQgY2xvdWQgb2YgcG9zaXRpdmUgd29yZHMgb2YgYmluZyBsZXhpY29uCndvcmRjbG91ZCh3b3JkcyA9IHBvc19iJHdvcmQsIGZyZXEgPSBwb3NfYiRGcmVxLCBtaW4uZnJlcSA9IDUwLAogICAgICAgICAgbWF4LndvcmRzPTEwMCwgc2NhbGU9YygyLCAxKSwgcmFuZG9tLm9yZGVyID0gRkFMU0UsIHJhbmRvbS5jb2xvciA9IEZBTFNFLCByb3QucGVyPTAuMzUsIAogICAgICAgICAgY29sb3JzPWJyZXdlci5wYWwoOCwgIkRhcmsyIikpCnRpdGxlKCJQb3NpdGl2ZSB3b3JkcyBpbiBCaW5nIExleGljb24iLCBvdXRlcj1GQUxTRSkKI0NyZWF0ZSB3b3JkIGNsb3VkIG9mIG5lZ2F0aXZlIHdvcmRzIG9mIGJpbmcgbGV4aWNvbgp3b3JkY2xvdWQod29yZHMgPSBuZWdfYiR3b3JkLCBmcmVxID0gbmVnX2IkRnJlcSwgbWluLmZyZXEgPSA1MCwKICAgICAgICAgIG1heC53b3Jkcz0xMDAsIHNjYWxlPWMoMiwgMSksIHJhbmRvbS5vcmRlciA9IEZBTFNFLCByYW5kb20uY29sb3IgPSBGQUxTRSwgcm90LnBlcj0wLjM1LCAKICAgICAgICAgIGNvbG9ycz1icmV3ZXIucGFsKDgsICJBY2NlbnQiKSkKdGl0bGUoIk5lZ2F0aXZlIHdvcmRzIGluIEJpbmcgTGV4aWNvbiIsIG91dGVyPUZBTFNFKQojQ3JlYXRlIHdvcmQgY2xvdWQgb2YgcG9zaXRpdmUgd29yZHMgb2YgbG91Z2hyYW4gbGV4aWNvbgp3b3JkY2xvdWQod29yZHMgPSBwb3NfbCR3b3JkLCBmcmVxID0gcG9zX2wkRnJlcSwgbWluLmZyZXEgPSA1MCwKICAgICAgICAgIG1heC53b3Jkcz0xMDAsIHNjYWxlPWMoMiwgMSksIHJhbmRvbS5vcmRlciA9IEZBTFNFLCByYW5kb20uY29sb3IgPSBGQUxTRSwgcm90LnBlcj0wLjM1LCAKICAgICAgICAgIGNvbG9ycz1icmV3ZXIucGFsKDgsICJEYXJrMiIpKQp0aXRsZSgiUG9zaXRpdmUgd29yZHMgaW4gTG91Z2hyYW4gTGV4aWNvbiIsIG91dGVyPUZBTFNFKQojQ3JlYXRlIHdvcmQgY2xvdWQgb2YgbmVnYXRpdmUgd29yZHMgb2YgbG91Z2hyYW4gbGV4aWNvbgp3b3JkY2xvdWQod29yZHMgPSBuZWdfbCR3b3JkLCBmcmVxID0gbmVnX2wkRnJlcSwgbWluLmZyZXEgPSA1MCwKICAgICAgICAgIG1heC53b3Jkcz0xMDAsIHNjYWxlPWMoMiwgMSksIHJhbmRvbS5vcmRlciA9IEZBTFNFLCByYW5kb20uY29sb3IgPSBGQUxTRSwgcm90LnBlcj0wLjM1LCAKICAgICAgICAgIGNvbG9ycz1icmV3ZXIucGFsKDgsICJBY2NlbnQiKSkKdGl0bGUoIk5lZ2F0aXZlIHdvcmRzIGluIExvdWdocmFuIExleGljb24iLCBvdXRlcj1GQUxTRSkKYGBgCgoKTGV0J3MgY2hlY2sgc29uZ3MgYmFzZWQgb24gTlJDIHNlbnRpbWVudCAoZXhjZXB0IHBvc2l0aXZlIGFuZCBuZWdhdGl2ZSkKCmBgYHtyfQpseXJpY3Nfd29yZHMgPC0gc2VsZWN0KGx5cmljcywgYygiYXJ0aXN0IiwgInNvbmciLCJ0ZXh0IikpCmx5cmljc193b3JkcyA8LSBseXJpY3Nfd29yZHMgJT4lIHVubmVzdF90b2tlbnMod29yZCwgdGV4dCkKaGVhZChseXJpY3Nfd29yZHMpCmRpbShseXJpY3Nfd29yZHMpCmBgYAoKYGBge3J9CmpveV9zIDwtIGx5cmljc193b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJucmMiKSAlPiUgCiAgZmlsdGVyKHNlbnRpbWVudCA9PSAiam95IikpIApqb3lfcyA8LSBhcy5kYXRhLmZyYW1lKHNvcnQodGFibGUoam95X3Mkc29uZykpKQpjb2x1bW5zX3NlbnRpbWVudCA8LSBjKCJTb25nIiwgIkZyZXEiKQpjb2xuYW1lcyhqb3lfcykgPC0gY29sdW1uc19zZW50aW1lbnQKdGFpbChqb3lfcywgMTApCgp0cnVzdF9zIDwtIGx5cmljc193b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJucmMiKSAlPiUgCiAgZmlsdGVyKHNlbnRpbWVudCA9PSAidHJ1c3QiKSkgCnRydXN0X3MgPC0gYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKHRydXN0X3Mkc29uZykpKQpjb2xuYW1lcyh0cnVzdF9zKSA8LSBjb2x1bW5zX3NlbnRpbWVudAp0YWlsKHRydXN0X3MsIDEwKQoKZmVhcl9zIDwtIGx5cmljc193b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJucmMiKSAlPiUgCiAgZmlsdGVyKHNlbnRpbWVudCA9PSAiZmVhciIpKSAKZmVhcl9zIDwtIGFzLmRhdGEuZnJhbWUoc29ydCh0YWJsZShmZWFyX3Mkc29uZykpKQpjb2xuYW1lcyhmZWFyX3MpIDwtIGNvbHVtbnNfc2VudGltZW50CgpzYWRuZXNzX3MgPC0gbHlyaWNzX3dvcmRzICU+JQogIGlubmVyX2pvaW4oZ2V0X3NlbnRpbWVudHMoIm5yYyIpICU+JSAKICBmaWx0ZXIoc2VudGltZW50ID09ICJzYWRuZXNzIikpIApzYWRuZXNzX3MgPC0gYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKHNhZG5lc3NfcyRzb25nKSkpCmNvbG5hbWVzKHNhZG5lc3NfcykgPC0gY29sdW1uc19zZW50aW1lbnQKCmFuZ2VyX3MgPC0gbHlyaWNzX3dvcmRzICU+JQogIGlubmVyX2pvaW4oZ2V0X3NlbnRpbWVudHMoIm5yYyIpICU+JSAKICBmaWx0ZXIoc2VudGltZW50ID09ICJhbmdlciIpKSAKYW5nZXJfcyA8LSBhcy5kYXRhLmZyYW1lKHNvcnQodGFibGUoYW5nZXJfcyRzb25nKSkpCmNvbG5hbWVzKGFuZ2VyX3MpIDwtIGNvbHVtbnNfc2VudGltZW50CgpzdXJwcmlzZV9zIDwtIGx5cmljc193b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJucmMiKSAlPiUgCiAgZmlsdGVyKHNlbnRpbWVudCA9PSAic3VycHJpc2UiKSkgCnN1cnByaXNlX3MgPC0gYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKHN1cnByaXNlX3Mkc29uZykpKQpjb2xuYW1lcyhzdXJwcmlzZV9zKSA8LSBjb2x1bW5zX3NlbnRpbWVudAoKZGlzZ3VzdF9zIDwtIGx5cmljc193b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJucmMiKSAlPiUgCiAgZmlsdGVyKHNlbnRpbWVudCA9PSAiZGlzZ3VzdCIpKSAKZGlzZ3VzdF9zIDwtIGFzLmRhdGEuZnJhbWUoc29ydCh0YWJsZShkaXNndXN0X3Mkc29uZykpKQpjb2xuYW1lcyhkaXNndXN0X3MpIDwtIGNvbHVtbnNfc2VudGltZW50CgphbnRpY2lwYXRpb25fcyA8LSBseXJpY3Nfd29yZHMgJT4lCiAgaW5uZXJfam9pbihnZXRfc2VudGltZW50cygibnJjIikgJT4lIAogIGZpbHRlcihzZW50aW1lbnQgPT0gImFudGljaXBhdGlvbiIpKSAKYW50aWNpcGF0aW9uX3MgPC0gYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKGFudGljaXBhdGlvbl9zJHNvbmcpKSkKY29sbmFtZXMoYW50aWNpcGF0aW9uX3MpIDwtIGNvbHVtbnNfc2VudGltZW50CmBgYAoKTGV0J3MgcGxvdCB0aGUgdG9wIDEwIHNvbmdzIGluIGVhY2ggY2F0ZWdvcnkKCgpgYGB7ciBmaWcud2lkdGg9OCwgZmlnLmhlaWdodD00LCBlY2hvPUZBTFNFfQpwMjMgPC0gZ2dwbG90KGRhdGEgPSB0YWlsKGpveV9zLCAxMCksIGFlcyhTb25nLCBGcmVxLCBmaWxsID0gU29uZykpICsKICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gRnJlcSksIHZqdXN0ID0gMS42LCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzKSArCiAgICAgIGdndGl0bGUoIkpveSIpICsKICAgICAgZ3VpZGVzKGZpbGw9RkFMU0UpICsgY29vcmRfZmxpcCgpICsKICAgICAgdGlsdF90aGVtZQpwMjQgPC0gZ2dwbG90KGRhdGEgPSB0YWlsKHRydXN0X3MsIDEwKSwgYWVzKFNvbmcsIEZyZXEsIGZpbGwgPSBTb25nKSkgKwogICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVxKSwgdmp1c3QgPSAxLjYsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMpICsKICAgICAgZ2d0aXRsZSgiVHJ1c3QiKSArCiAgICAgIGd1aWRlcyhmaWxsPUZBTFNFKSArIGNvb3JkX2ZsaXAoKSArCiAgICAgIHRpbHRfdGhlbWUKcDI1IDwtIGdncGxvdChkYXRhID0gdGFpbChmZWFyX3MsIDEwKSwgYWVzKFNvbmcsIEZyZXEsIGZpbGwgPSBTb25nKSkgKwogICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVxKSwgdmp1c3QgPSAxLjYsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMpICsKICAgICAgZ2d0aXRsZSgiRmVhciIpICsKICAgICAgZ3VpZGVzKGZpbGw9RkFMU0UpICsgY29vcmRfZmxpcCgpICsKICAgICAgdGlsdF90aGVtZQpwMjYgPC0gZ2dwbG90KGRhdGEgPSB0YWlsKHNhZG5lc3NfcywgMTApLCBhZXMoU29uZywgRnJlcSwgZmlsbCA9IFNvbmcpKSArCiAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLCB2anVzdCA9IDEuNiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMykgKwogICAgICBnZ3RpdGxlKCJTYWRuZXNzIikgKwogICAgICBndWlkZXMoZmlsbD1GQUxTRSkgKyBjb29yZF9mbGlwKCkgKwogICAgICB0aWx0X3RoZW1lCnAyNyA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwoYW5nZXJfcywgMTApLCBhZXMoU29uZywgRnJlcSwgZmlsbCA9IFNvbmcpKSArCiAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLCB2anVzdCA9IDEuNiwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMykgKwogICAgICBnZ3RpdGxlKCJBbmdlciIpICsKICAgICAgZ3VpZGVzKGZpbGw9RkFMU0UpICsgY29vcmRfZmxpcCgpICsKICAgICAgdGlsdF90aGVtZQpwMjggPC0gZ2dwbG90KGRhdGEgPSB0YWlsKHN1cnByaXNlX3MsIDEwKSwgYWVzKFNvbmcsIEZyZXEsIGZpbGwgPSBTb25nKSkgKwogICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVxKSwgdmp1c3QgPSAxLjYsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMpICsKICAgICAgZ2d0aXRsZSgiU3VycHJpc2UiKSArCiAgICAgIGd1aWRlcyhmaWxsPUZBTFNFKSArIGNvb3JkX2ZsaXAoKSArCiAgICAgIHRpbHRfdGhlbWUKcDI5IDwtIGdncGxvdChkYXRhID0gdGFpbChkaXNndXN0X3MsIDEwKSwgYWVzKFNvbmcsIEZyZXEsIGZpbGwgPSBTb25nKSkgKwogICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVxKSwgdmp1c3QgPSAxLjYsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMpICsKICAgICAgZ2d0aXRsZSgiRGlzZ3VzdCIpICsKICAgICAgZ3VpZGVzKGZpbGw9RkFMU0UpICsgY29vcmRfZmxpcCgpICsKICAgICAgdGlsdF90aGVtZQpwMzAgPC0gZ2dwbG90KGRhdGEgPSB0YWlsKGFudGljaXBhdGlvbl9zLCAxMCksIGFlcyhTb25nLCBGcmVxLCBmaWxsID0gU29uZykpICsKICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gRnJlcSksIHZqdXN0ID0gMS42LCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzKSArCiAgICAgIGdndGl0bGUoIkFudGljaXBhdGlvbiIpICsKICAgICAgZ3VpZGVzKGZpbGw9RkFMU0UpICsgY29vcmRfZmxpcCgpICsKICAgICAgdGlsdF90aGVtZQoKbXVsdGlwbG90KHAyMywgcDI0LCBwMjUsIHAyNiwgcDI3LCBwMjgsIHAyOSxwMzAsIGxheW91dCA9IG1hdHJpeChjKDEsMiwzLDQsNSw2LDcsOCksIG5yb3c9MiwgYnlyb3c9VFJVRSkpCgpgYGAKCgoKTGV0J3MgZG8gdGhlIHNhbWUgZm9yIFBvc2l0aXZlIGFuZCBOZWdhdGl2ZSBzZW50aW1lbnQgaW4gTlJDIGxleGljb24gY2F0ZW9nb3J5LgpgYGB7ciBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD0yLCBlY2hvPUZBTFNFfQpwb3NfcyA8LSBseXJpY3Nfd29yZHMgJT4lCiAgaW5uZXJfam9pbihnZXRfc2VudGltZW50cygibnJjIikgJT4lIAogIGZpbHRlcihzZW50aW1lbnQgPT0gInBvc2l0aXZlIikpIApwb3NfcyA8LSBhcy5kYXRhLmZyYW1lKHNvcnQodGFibGUocG9zX3Mkc29uZykpKQpjb2xuYW1lcyhwb3NfcykgPC0gY29sdW1uc19zZW50aW1lbnQKCm5lZ19zIDwtIGx5cmljc193b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJucmMiKSAlPiUgCiAgZmlsdGVyKHNlbnRpbWVudCA9PSAibmVnYXRpdmUiKSkgCm5lZ19zIDwtIGFzLmRhdGEuZnJhbWUoc29ydCh0YWJsZShuZWdfcyRzb25nKSkpCmNvbG5hbWVzKG5lZ19zKSA8LSBjb2x1bW5zX3NlbnRpbWVudAoKcDMxIDwtIGdncGxvdChkYXRhID0gdGFpbChwb3NfcywgMjApLCBhZXMoU29uZywgRnJlcSwgZmlsbCA9IFNvbmcpKSArCiAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzKSArCiAgICAgIGdndGl0bGUoIlBvc2l0aXZlIChOUkMpIikgKwogICAgICBndWlkZXMoZmlsbD1GQUxTRSkgKyBjb29yZF9mbGlwKCkgKwogICAgICB0aWx0X3RoZW1lCnAzMiA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwobmVnX3MsIDIwKSwgYWVzKFNvbmcsIEZyZXEsIGZpbGwgPSBTb25nKSkgKwogICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVxKSAsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMpICsKICAgICAgZ2d0aXRsZSgiTmVnYXRpdmUgKE5SQykiKSArCiAgICAgIGd1aWRlcyhmaWxsPUZBTFNFKSArIGNvb3JkX2ZsaXAoKSArCiAgICAgIHRpbHRfdGhlbWUKbXVsdGlwbG90KHAzMSwgcDMyLCBjb2xzPTIpCmBgYAoKTGV0IHVzIGZpbmQgcG9zaXRpdmUgYW5kIG5lZ2F0aXZlIHNvbmdzIGJhc2VkIG9uIGJpbmcgYW5kIGxvdWdocmFuIGxleGljb24gY2F0ZW9nb3JpZXMuCgpgYGB7ciBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NSwgZWNobz1GQUxTRX0KcG9zX2JzIDwtIGx5cmljc193b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJiaW5nIikgJT4lIAogIGZpbHRlcihzZW50aW1lbnQgPT0gInBvc2l0aXZlIikpIApwb3NfYnMgPC0gYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKHBvc19icyRzb25nKSkpCmNvbG5hbWVzKHBvc19icykgPC0gY29sdW1uc19zZW50aW1lbnQKCm5lZ19icyA8LSBseXJpY3Nfd29yZHMgJT4lCiAgaW5uZXJfam9pbihnZXRfc2VudGltZW50cygiYmluZyIpICU+JSAKICBmaWx0ZXIoc2VudGltZW50ID09ICJuZWdhdGl2ZSIpKSAKbmVnX2JzIDwtIGFzLmRhdGEuZnJhbWUoc29ydCh0YWJsZShuZWdfYnMkc29uZykpKQpjb2xuYW1lcyhuZWdfYnMpIDwtIGNvbHVtbnNfc2VudGltZW50Cgpwb3NfbHMgPC0gbHlyaWNzX3dvcmRzICU+JSAKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJsb3VnaHJhbiIpICU+JSAKICBmaWx0ZXIoc2VudGltZW50ID09ICJwb3NpdGl2ZSIpKSAKcG9zX2xzIDwtIGFzLmRhdGEuZnJhbWUoc29ydCh0YWJsZShwb3NfbHMkc29uZykpKQpjb2xuYW1lcyhwb3NfbHMpIDwtIGNvbHVtbnNfc2VudGltZW50CgpuZWdfbHMgPC0gbHlyaWNzX3dvcmRzICU+JQogIGlubmVyX2pvaW4oZ2V0X3NlbnRpbWVudHMoImxvdWdocmFuIikgJT4lIAogIGZpbHRlcihzZW50aW1lbnQgPT0gIm5lZ2F0aXZlIikpIApuZWdfbHMgPC0gYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKG5lZ19scyRzb25nKSkpCmNvbG5hbWVzKG5lZ19scykgPC0gY29sdW1uc19zZW50aW1lbnQKCnAzMyA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwocG9zX2JzLCAyMCksIGFlcyhTb25nLCBGcmVxLCBmaWxsID0gU29uZykpICsKICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gRnJlcSksIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMpICsKICAgICAgZ2d0aXRsZSgiUG9zaXRpdmUgKEJJTkcpIikgKwogICAgICBndWlkZXMoZmlsbD1GQUxTRSkgKyBjb29yZF9mbGlwKCkgKwogICAgICB0aWx0X3RoZW1lCnAzNCA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwobmVnX2JzLCAyMCksIGFlcyhTb25nLCBGcmVxLCBmaWxsID0gU29uZykpICsKICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gRnJlcSksIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMpICsKICAgICAgZ2d0aXRsZSgiTmVnYXRpdmUgKEJJTkcpIikgKwogICAgICBndWlkZXMoZmlsbD1GQUxTRSkgKyBjb29yZF9mbGlwKCkgKwogICAgICB0aWx0X3RoZW1lCnAzNSA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwocG9zX2xzLCAyMCksIGFlcyhTb25nLCBGcmVxLCBmaWxsID0gU29uZykpICsKICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gRnJlcSksIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMpICsKICAgICAgZ2d0aXRsZSgiUG9zaXRpdmUgKExPVUdIUkFOKSIpICsKICAgICAgZ3VpZGVzKGZpbGw9RkFMU0UpICsgY29vcmRfZmxpcCgpICsKICAgICAgdGlsdF90aGVtZQpwMzYgPC0gZ2dwbG90KGRhdGEgPSB0YWlsKG5lZ19scywgMjApLCBhZXMoU29uZywgRnJlcSwgZmlsbCA9IFNvbmcpKSArCiAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzKSArCiAgICAgIGdndGl0bGUoIk5lZ2F0aXZlIChMT1VHSFJBTikiKSArCiAgICAgIGd1aWRlcyhmaWxsPUZBTFNFKSArIGNvb3JkX2ZsaXAoKSArCiAgICAgIHRpbHRfdGhlbWUKbXVsdGlwbG90KHAzMywgcDM0LHAzNSwgcDM2LGxheW91dCA9IG1hdHJpeChjKDEsMiwzLDQpLCBucm93PTIsIGJ5cm93PVRSVUUpKQoKYGBgCgpUaGUgcG9zaXRpdmUgYW5kIG5lZ2F0aXZlIHNvbmdzIGluIGVhY2ggY2F0ZWdvcnkgYXJlIGRpZmZlcmVudC4gVGhpcyBpcyBzb21ldGhpbmcga25vd24gYWxyZWFkeSwgc2luY2UgdGhlIHBvc2l0aXZlIHdvcmRzIGFuZCBuZWdhdGl2ZSB3b3JkcyBpbiBlY2ggY2F0ZWdvcmllcyB3ZXJlIGFsc28gZGlmZmVyZW50LgoKVGhlIHNhbWUgYW5hbHlzaXMgY2FuIGJlIGRvbmUgZm9yIGFydGlzdHMuIExldCdzIGNoZWNrIG91dCBhcnRpc3RzIHdobyB3cml0ZSBtb3N0IHNvbmdzIGluIGVhY2ggTlJDIGxleGljb24gc2VudGltZW50IGNhdGVvZ3J5LgoKYGBge3J9CmpveV9hIDwtIGx5cmljc193b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJucmMiKSAlPiUgCiAgZmlsdGVyKHNlbnRpbWVudCA9PSAiam95IikpIApqb3lfYSA8LSBhcy5kYXRhLmZyYW1lKHNvcnQodGFibGUoam95X2EkYXJ0aXN0KSkpCmNvbHVtbnNfc2VudGltZW50IDwtIGMoImFydGlzdCIsICJGcmVxIikKY29sbmFtZXMoam95X2EpIDwtIGNvbHVtbnNfc2VudGltZW50CnRhaWwoam95X2EsIDEwKQoKdHJ1c3RfYSA8LSBseXJpY3Nfd29yZHMgJT4lCiAgaW5uZXJfam9pbihnZXRfc2VudGltZW50cygibnJjIikgJT4lIAogIGZpbHRlcihzZW50aW1lbnQgPT0gInRydXN0IikpIAp0cnVzdF9hIDwtIGFzLmRhdGEuZnJhbWUoc29ydCh0YWJsZSh0cnVzdF9hJGFydGlzdCkpKQpjb2xuYW1lcyh0cnVzdF9hKSA8LSBjb2x1bW5zX3NlbnRpbWVudAp0YWlsKHRydXN0X2EsIDEwKQoKZmVhcl9hIDwtIGx5cmljc193b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJucmMiKSAlPiUgCiAgZmlsdGVyKHNlbnRpbWVudCA9PSAiZmVhciIpKSAKZmVhcl9hIDwtIGFzLmRhdGEuZnJhbWUoc29ydCh0YWJsZShmZWFyX2EkYXJ0aXN0KSkpCmNvbG5hbWVzKGZlYXJfYSkgPC0gY29sdW1uc19zZW50aW1lbnQKCnNhZG5lc3NfYSA8LSBseXJpY3Nfd29yZHMgJT4lCiAgaW5uZXJfam9pbihnZXRfc2VudGltZW50cygibnJjIikgJT4lIAogIGZpbHRlcihzZW50aW1lbnQgPT0gInNhZG5lc3MiKSkgCnNhZG5lc3NfYSA8LSBhcy5kYXRhLmZyYW1lKHNvcnQodGFibGUoc2FkbmVzc19hJGFydGlzdCkpKQpjb2xuYW1lcyhzYWRuZXNzX2EpIDwtIGNvbHVtbnNfc2VudGltZW50Cgphbmdlcl9hIDwtIGx5cmljc193b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJucmMiKSAlPiUgCiAgZmlsdGVyKHNlbnRpbWVudCA9PSAiYW5nZXIiKSkgCmFuZ2VyX2EgPC0gYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKGFuZ2VyX2EkYXJ0aXN0KSkpCmNvbG5hbWVzKGFuZ2VyX2EpIDwtIGNvbHVtbnNfc2VudGltZW50CgpzdXJwcmlzZV9hIDwtIGx5cmljc193b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJucmMiKSAlPiUgCiAgZmlsdGVyKHNlbnRpbWVudCA9PSAic3VycHJpc2UiKSkgCnN1cnByaXNlX2EgPC0gYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKHN1cnByaXNlX2EkYXJ0aXN0KSkpCmNvbG5hbWVzKHN1cnByaXNlX2EpIDwtIGNvbHVtbnNfc2VudGltZW50CgpkaXNndXN0X2EgPC0gbHlyaWNzX3dvcmRzICU+JQogIGlubmVyX2pvaW4oZ2V0X3NlbnRpbWVudHMoIm5yYyIpICU+JSAKICBmaWx0ZXIoc2VudGltZW50ID09ICJkaXNndXN0IikpIApkaXNndXN0X2EgPC0gYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKGRpc2d1c3RfYSRhcnRpc3QpKSkKY29sbmFtZXMoZGlzZ3VzdF9hKSA8LSBjb2x1bW5zX3NlbnRpbWVudAoKYW50aWNpcGF0aW9uX2EgPC0gbHlyaWNzX3dvcmRzICU+JQogIGlubmVyX2pvaW4oZ2V0X3NlbnRpbWVudHMoIm5yYyIpICU+JSAKICBmaWx0ZXIoc2VudGltZW50ID09ICJhbnRpY2lwYXRpb24iKSkgCmFudGljaXBhdGlvbl9hIDwtIGFzLmRhdGEuZnJhbWUoc29ydCh0YWJsZShhbnRpY2lwYXRpb25fYSRhcnRpc3QpKSkKY29sbmFtZXMoYW50aWNpcGF0aW9uX2EpIDwtIGNvbHVtbnNfc2VudGltZW50CmBgYAoKTGV0J3MgcGxvdCB0aGUgdG9wIDEwIGFydGlzdHMgaW4gZWFjaCBjYXRlZ29yeQoKCmBgYHtyIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTQsIGVjaG89RkFMU0V9CnAzNyA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwoam95X2EsIDEwKSwgYWVzKGFydGlzdCwgRnJlcSwgZmlsbCA9IGFydGlzdCkpICsKICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gRnJlcSksIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMpICsKICAgICAgZ2d0aXRsZSgiSm95IikgKwogICAgICBndWlkZXMoZmlsbD1GQUxTRSkgKyBjb29yZF9mbGlwKCkgKwogICAgICB0aWx0X3RoZW1lCnAzOCA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwodHJ1c3RfYSwgMTApLCBhZXMoYXJ0aXN0LCBGcmVxLCBmaWxsID0gYXJ0aXN0KSkgKwogICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVxKSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMykgKwogICAgICBnZ3RpdGxlKCJUcnVzdCIpICsKICAgICAgZ3VpZGVzKGZpbGw9RkFMU0UpICsgY29vcmRfZmxpcCgpICsKICAgICAgdGlsdF90aGVtZQpwMzkgPC0gZ2dwbG90KGRhdGEgPSB0YWlsKGZlYXJfYSwgMTApLCBhZXMoYXJ0aXN0LCBGcmVxLCBmaWxsID0gYXJ0aXN0KSkgKwogICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVxKSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMykgKwogICAgICBnZ3RpdGxlKCJGZWFyIikgKwogICAgICBndWlkZXMoZmlsbD1GQUxTRSkgKyBjb29yZF9mbGlwKCkgKwogICAgICB0aWx0X3RoZW1lCnA0MCA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwoc2FkbmVzc19hLCAxMCksIGFlcyhhcnRpc3QsIEZyZXEsIGZpbGwgPSBhcnRpc3QpKSArCiAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzKSArCiAgICAgIGdndGl0bGUoIlNhZG5lc3MiKSArCiAgICAgIGd1aWRlcyhmaWxsPUZBTFNFKSArIGNvb3JkX2ZsaXAoKSArCiAgICAgIHRpbHRfdGhlbWUKcDQxIDwtIGdncGxvdChkYXRhID0gdGFpbChhbmdlcl9hLCAxMCksIGFlcyhhcnRpc3QsIEZyZXEsIGZpbGwgPSBhcnRpc3QpKSArCiAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzKSArCiAgICAgIGdndGl0bGUoIkFuZ2VyIikgKwogICAgICBndWlkZXMoZmlsbD1GQUxTRSkgKyBjb29yZF9mbGlwKCkgKwogICAgICB0aWx0X3RoZW1lCnA0MiA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwoc3VycHJpc2VfYSwgMTApLCBhZXMoYXJ0aXN0LCBGcmVxLCBmaWxsID0gYXJ0aXN0KSkgKwogICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVxKSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMykgKwogICAgICBnZ3RpdGxlKCJTdXJwcmlzZSIpICsKICAgICAgZ3VpZGVzKGZpbGw9RkFMU0UpICsgY29vcmRfZmxpcCgpICsKICAgICAgdGlsdF90aGVtZQpwNDMgPC0gZ2dwbG90KGRhdGEgPSB0YWlsKGRpc2d1c3RfYSwgMTApLCBhZXMoYXJ0aXN0LCBGcmVxLCBmaWxsID0gYXJ0aXN0KSkgKwogICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVxKSxjb2xvciA9ICJibGFjayIsIHNpemUgPSAzKSArCiAgICAgIGdndGl0bGUoIkRpc2d1c3QiKSArCiAgICAgIGd1aWRlcyhmaWxsPUZBTFNFKSArIGNvb3JkX2ZsaXAoKSArCiAgICAgIHRpbHRfdGhlbWUKcDQ0IDwtIGdncGxvdChkYXRhID0gdGFpbChhbnRpY2lwYXRpb25fYSwgMTApLCBhZXMoYXJ0aXN0LCBGcmVxLCBmaWxsID0gYXJ0aXN0KSkgKwogICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVxKSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMykgKwogICAgICBnZ3RpdGxlKCJBbnRpY2lwYXRpb24iKSArCiAgICAgIGd1aWRlcyhmaWxsPUZBTFNFKSArIGNvb3JkX2ZsaXAoKSArCiAgICAgIHRpbHRfdGhlbWUKCm11bHRpcGxvdChwMzcsIHAzOCwgcDM5LCBwNDAsIHA0MSwgcDQyLCBwNDMsIHA0NCwgbGF5b3V0ID0gbWF0cml4KGMoMSwyLDMsNCw1LDYsNyw4KSwgbnJvdz0yLCBieXJvdz1UUlVFKSkKCmBgYAoKTGV0J3MgZG8gdGhlIHNhbWUgZm9yIFBvc2l0aXZlIGFuZCBOZWdhdGl2ZSBzZW50aW1lbnQgaW4gTlJDIGxleGljb24gY2F0ZW9nb3J5LgpgYGB7ciBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD0yLCBlY2hvPUZBTFNFfQpwb3NfYSA8LSBseXJpY3Nfd29yZHMgJT4lCiAgaW5uZXJfam9pbihnZXRfc2VudGltZW50cygibnJjIikgJT4lIAogIGZpbHRlcihzZW50aW1lbnQgPT0gInBvc2l0aXZlIikpIApwb3NfYSA8LSBhcy5kYXRhLmZyYW1lKHNvcnQodGFibGUocG9zX2EkYXJ0aXN0KSkpCmNvbG5hbWVzKHBvc19hKSA8LSBjb2x1bW5zX3NlbnRpbWVudAoKbmVnX2EgPC0gbHlyaWNzX3dvcmRzICU+JQogIGlubmVyX2pvaW4oZ2V0X3NlbnRpbWVudHMoIm5yYyIpICU+JSAKICBmaWx0ZXIoc2VudGltZW50ID09ICJuZWdhdGl2ZSIpKSAKbmVnX2EgPC0gYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKG5lZ19hJGFydGlzdCkpKQpjb2xuYW1lcyhuZWdfYSkgPC0gY29sdW1uc19zZW50aW1lbnQKCnA0NSA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwocG9zX2EsIDE1KSwgYWVzKGFydGlzdCwgRnJlcSwgZmlsbCA9IGFydGlzdCkpICsKICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gRnJlcSksIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMpICsKICAgICAgZ2d0aXRsZSgiUG9zaXRpdmUgKE5SQykiKSArCiAgICAgIGd1aWRlcyhmaWxsPUZBTFNFKSArIGNvb3JkX2ZsaXAoKSArCiAgICAgIHRpbHRfdGhlbWUKcDQ2IDwtIGdncGxvdChkYXRhID0gdGFpbChuZWdfYSwgMTUpLCBhZXMoYXJ0aXN0LCBGcmVxLCBmaWxsID0gYXJ0aXN0KSkgKwogICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVxKSAsIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMpICsKICAgICAgZ2d0aXRsZSgiTmVnYXRpdmUgKE5SQykiKSArCiAgICAgIGd1aWRlcyhmaWxsPUZBTFNFKSArIGNvb3JkX2ZsaXAoKSArCiAgICAgIHRpbHRfdGhlbWUKbXVsdGlwbG90KHA0NSwgcDQ2LCBjb2xzPTIpCmBgYAoKTGV0IHVzIGZpbmQgcG9zaXRpdmUgYW5kIG5lZ2F0aXZlIHNvbmdzIGJhc2VkIG9uIGJpbmcgYW5kIGxvdWdocmFuIGxleGljb24gY2F0ZW9nb3JpZXMuCgpgYGB7ciBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NSwgZWNobz1GQUxTRX0KcG9zX2JhIDwtIGx5cmljc193b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJiaW5nIikgJT4lIAogIGZpbHRlcihzZW50aW1lbnQgPT0gInBvc2l0aXZlIikpIApwb3NfYmEgPC0gYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKHBvc19iYSRhcnRpc3QpKSkKY29sbmFtZXMocG9zX2JhKSA8LSBjb2x1bW5zX3NlbnRpbWVudAoKbmVnX2JhIDwtIGx5cmljc193b3JkcyAlPiUKICBpbm5lcl9qb2luKGdldF9zZW50aW1lbnRzKCJiaW5nIikgJT4lIAogIGZpbHRlcihzZW50aW1lbnQgPT0gIm5lZ2F0aXZlIikpIApuZWdfYmEgPC0gYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKG5lZ19iYSRhcnRpc3QpKSkKY29sbmFtZXMobmVnX2JhKSA8LSBjb2x1bW5zX3NlbnRpbWVudAoKcG9zX2xhIDwtIGx5cmljc193b3JkcyAlPiUgCiAgaW5uZXJfam9pbihnZXRfc2VudGltZW50cygibG91Z2hyYW4iKSAlPiUgCiAgZmlsdGVyKHNlbnRpbWVudCA9PSAicG9zaXRpdmUiKSkgCnBvc19sYSA8LSBhcy5kYXRhLmZyYW1lKHNvcnQodGFibGUocG9zX2xhJGFydGlzdCkpKQpjb2xuYW1lcyhwb3NfbGEpIDwtIGNvbHVtbnNfc2VudGltZW50CgpuZWdfbGEgPC0gbHlyaWNzX3dvcmRzICU+JQogIGlubmVyX2pvaW4oZ2V0X3NlbnRpbWVudHMoImxvdWdocmFuIikgJT4lIAogIGZpbHRlcihzZW50aW1lbnQgPT0gIm5lZ2F0aXZlIikpIApuZWdfbGEgPC0gYXMuZGF0YS5mcmFtZShzb3J0KHRhYmxlKG5lZ19sYSRhcnRpc3QpKSkKY29sbmFtZXMobmVnX2xhKSA8LSBjb2x1bW5zX3NlbnRpbWVudAoKcDQ3IDwtIGdncGxvdChkYXRhID0gdGFpbChwb3NfYmEsIDE1KSwgYWVzKGFydGlzdCwgRnJlcSwgZmlsbCA9IGFydGlzdCkpICsKICAgICAgZ2VvbV9iYXIocG9zaXRpb24gPSAiZG9kZ2UiLCBzdGF0ID0gImlkZW50aXR5IikgKwogICAgICBnZW9tX3RleHQoYWVzKGxhYmVsID0gRnJlcSksIGNvbG9yID0gImJsYWNrIiwgc2l6ZSA9IDMpICsKICAgICAgZ2d0aXRsZSgiUG9zaXRpdmUgKEJJTkcpIikgKwogICAgICBndWlkZXMoZmlsbD1GQUxTRSkgKyBjb29yZF9mbGlwKCkgKwogICAgICB0aWx0X3RoZW1lCnA0OCA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwobmVnX2JhLCAxNSksIGFlcyhhcnRpc3QsIEZyZXEsIGZpbGwgPSBhcnRpc3QpKSArCiAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzKSArCiAgICAgIGdndGl0bGUoIk5lZ2F0aXZlIChCSU5HKSIpICsKICAgICAgZ3VpZGVzKGZpbGw9RkFMU0UpICsgY29vcmRfZmxpcCgpICsKICAgICAgdGlsdF90aGVtZQpwNDkgPC0gZ2dwbG90KGRhdGEgPSB0YWlsKHBvc19sYSwgMTUpLCBhZXMoYXJ0aXN0LCBGcmVxLCBmaWxsID0gYXJ0aXN0KSkgKwogICAgICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBGcmVxKSwgY29sb3IgPSAiYmxhY2siLCBzaXplID0gMykgKwogICAgICBnZ3RpdGxlKCJQb3NpdGl2ZSAoTE9VR0hSQU4pIikgKwogICAgICBndWlkZXMoZmlsbD1GQUxTRSkgKyBjb29yZF9mbGlwKCkgKwogICAgICB0aWx0X3RoZW1lCnA1MCA8LSBnZ3Bsb3QoZGF0YSA9IHRhaWwobmVnX2xhLCAxNSksIGFlcyhhcnRpc3QsIEZyZXEsIGZpbGwgPSBhcnRpc3QpKSArCiAgICAgIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICsKICAgICAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IEZyZXEpLCBjb2xvciA9ICJibGFjayIsIHNpemUgPSAzKSArCiAgICAgIGdndGl0bGUoIk5lZ2F0aXZlIChMT1VHSFJBTikiKSArCiAgICAgIGd1aWRlcyhmaWxsPUZBTFNFKSArIGNvb3JkX2ZsaXAoKSArCiAgICAgIHRpbHRfdGhlbWUKbXVsdGlwbG90KHA0NywgcDQ4LHA0OSwgcDUwLGxheW91dCA9IG1hdHJpeChjKDEsMiwzLDQpLCBucm93PTIsIGJ5cm93PVRSVUUpKQoKYGBgCgpMZXQncyBjaGVjayBvdXQgYmlncmFtcyBpbiB0aGUgc29uZ3MgbHlyaWNzCgpgYGB7ciBlY2hvPUZBTFNFfQpseXJpY3NfYmlncmFtIDwtIHVubmVzdF90b2tlbnMobHlyaWNzLCBpbnB1dCA9IHRleHQsIG91dHB1dCA9IGJpZ3JhbSwgdG9rZW4gPSAibmdyYW1zIiwgbj0yKQoKCmJpZ3JhbV9maWx0ZXJlZDwtbHlyaWNzX2JpZ3JhbSAlPiVzZXBhcmF0ZShiaWdyYW0sYygid29yZDEiLCJ3b3JkMiIsc2VwPSIgIikpJT4lCmZpbHRlcighd29yZDEgJWluJSBzdG9wX3dvcmRzJHdvcmQpICU+JQogIGZpbHRlcighd29yZDIgJWluJSBzdG9wX3dvcmRzJHdvcmQpCiAgCiAKICBiaWdyYW1fdW5pdGVkIDwtIGJpZ3JhbV9maWx0ZXJlZCAlPiUKICB1bml0ZShiaWdyYW0sIHdvcmQxLCB3b3JkMiwgc2VwID0gIiAiKQpoZWFkKGJpZ3JhbV91bml0ZWQpCgoKYGBgCgpgYGB7cn0KICAKYmlncmFtX2NvdW50cyA8LSBiaWdyYW1fdW5pdGVkICU+JSAKICBjb3VudChiaWdyYW0sIHNvcnQgPSBUUlVFKQogIGhlYWQoYmlncmFtX2NvdW50cykgCiAgCiAgIAogIGJpZ3JhbV9jb3VudHMgJT4lIGFycmFuZ2UoZGVzYyhuKSklPiUgaGVhZCgyMCklPiVnZ3Bsb3QoYWVzKHg9ZmFjdG9yKGJpZ3JhbSxsZXZlbHM9YmlncmFtKSx5PW4pKStnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIsZmlsbD0iI0ZGM0U0NSIpK2xhYnModGl0bGU9IlRvcCAyMCBiaWdyYW0gd29yZHMgaW4gU29uZ3MiKStjb29yZF9mbGlwKCkKICAKIAogIHdvcmRjbG91ZChiaWdyYW1fY291bnRzJGJpZ3JhbSxiaWdyYW1fY291bnRzJG4sbWF4LndvcmRzPTUwLHJhbmRvbS5vcmRlciA9IEYsY29sb3JzPWMoIiM5RTAxNDIiLCAiI0Q1M0U0RiIsICIjRjQ2RDQzIiAsIiNGREFFNjEiLCAiI0ZFRTA4QiIsICIjRTZGNTk4IiAsIiNBQkREQTQiICwiIzY2QzJBNSIgLCIjMzI4OEJEIiwgIiM1RTRGQTIiKSkKdGl0bGUobWFpbj0iQmlncmFtIHdvcmRjbG91ZCIpCmBgYAoKCgoKCgo=